1 package ldvalue
2
3 import (
4 "fmt"
5 "sort"
6 "testing"
7
8 "github.com/stretchr/testify/assert"
9 )
10
11 func TestNilValueMap(t *testing.T) {
12 m := ValueMap{}
13 assert.False(t, m.IsDefined())
14 assert.Equal(t, 0, m.Count())
15 assert.Equal(t, Null(), m.Get("item"))
16 }
17
18 func TestCopyValueMap(t *testing.T) {
19 m := map[string]Value{"item0": Int(1), "item1": Int(2)}
20 vm1 := CopyValueMap(m)
21 assert.Equal(t, m, vm1.data)
22 shouldNotBeSameMap(t, m, vm1.data)
23
24 vm2 := CopyValueMap(nil)
25 assert.Nil(t, vm2.data)
26 assert.False(t, vm2.IsDefined())
27
28 vm3 := CopyValueMap(map[string]Value{})
29 assert.NotNil(t, vm3.data)
30 assert.Equal(t, 0, len(vm3.data))
31 assert.True(t, vm3.IsDefined())
32 }
33
34 func TestCopyArbitraryValueMap(t *testing.T) {
35 m := map[string]interface{}{"item0": "a", "item1": "b"}
36 vm1 := CopyArbitraryValueMap(m)
37 assert.Equal(t, map[string]Value{"item0": String("a"), "item1": String("b")}, vm1.data)
38
39 vm2 := CopyArbitraryValueMap(nil)
40 assert.Nil(t, vm2.data)
41 }
42
43 func TestValueMapBuild(t *testing.T) {
44 item0 := String("a")
45 item1 := Int(1)
46 b := ValueMapBuild().Set("item0", item0).Set("item1", item1)
47 valueMap := b.Build()
48
49 assert.Equal(t, 2, valueMap.Count())
50 keys := valueMap.Keys(nil)
51 sort.Strings(keys)
52 assert.Equal(t, []string{"item0", "item1"}, keys)
53
54 item0x := Bool(true)
55 b.Set("item0", item0x)
56 valueMapAfterModifyingBuilder := b.Build()
57 assert.Equal(t, item0x, valueMapAfterModifyingBuilder.Get("item0"))
58 assert.Equal(t, item0, valueMap.Get("item0"))
59
60 assert.True(t, valueMap.IsDefined())
61
62 m2 := ValueMapBuildWithCapacity(3).Set("item0", item0).Set("item1", item1).Build()
63 assert.Equal(t, valueMap, m2)
64 }
65
66 func TestValueMapBuildFromMap(t *testing.T) {
67 m0 := ValueMapBuild().Set("item0", Int(1)).Set("item1", Int(2)).Build()
68
69 m1 := ValueMapBuildFromMap(m0).Build()
70 assert.Equal(t, m0, m1)
71 shouldBeSameMap(t, m0.data, m1.data)
72
73 m2 := ValueMapBuild().Set("item2", Int(3))
74 m2.SetAllFromValueMap(m0)
75 assert.Equal(t, ValueMapBuild().Set("item0", Int(1)).Set("item1", Int(2)).Set("item2", Int(3)).Build(), m2.Build())
76
77
78 m3 := ValueMapBuild().Set("item0", Int(1)).Build()
79 m4 := ValueMapBuildFromMap(m3).Set("item1", Int(2)).Build()
80 assert.Equal(t, ValueMapBuild().Set("item0", Int(1)).Set("item1", Int(2)).Build(), m4)
81 shouldNotBeSameMap(t, m3.data, m4.data)
82 m5 := ValueMapBuild().SetAllFromValueMap(m3).Set("item1", Int(2)).Build()
83 assert.NotEqual(t, m3, m5)
84 shouldNotBeSameMap(t, m3.data, m5.data)
85 assert.Equal(t, m4, m5)
86 }
87
88 func TestValueMapBuilderRemove(t *testing.T) {
89 m0 := ValueMapBuild().Set("item0", Int(1)).Set("item1", Int(2)).Remove("item0").Build()
90 assert.Equal(t, ValueMapBuild().Set("item1", Int(2)).Build(), m0)
91
92 m1 := ValueMapBuildFromMap(m0).Remove("item1").Build()
93 assert.Equal(t, ValueMapBuild().Build(), m1)
94 assert.NotEqual(t, m0, m1)
95 shouldNotBeSameMap(t, m0.data, m1.data)
96 }
97
98 func TestValueMapBuilderHasKey(t *testing.T) {
99 var b ValueMapBuilder
100 assert.False(t, b.HasKey("key1"))
101 assert.False(t, b.HasKey("key2"))
102
103 b.Set("key1", Int(1))
104 assert.True(t, b.HasKey("key1"))
105 assert.False(t, b.HasKey("key2"))
106
107 b.Set("key2", Int(2))
108 assert.True(t, b.HasKey("key1"))
109 assert.True(t, b.HasKey("key2"))
110
111 b.Remove("key1")
112 assert.False(t, b.HasKey("key1"))
113 assert.True(t, b.HasKey("key2"))
114 }
115
116 func TestValueMapBuilderSafety(t *testing.T) {
117
118 var emptyInstance ValueMapBuilder
119 emptyInstance.Set("key", Int(1))
120 assert.Equal(t, ValueMapBuild().Set("key", Int(1)).Build(), emptyInstance.Build())
121
122
123 var nilPtr *ValueMapBuilder
124 assert.Nil(t, nilPtr.Set("key", Int(1)))
125 assert.Nil(t, nilPtr.SetAllFromValueMap(ValueMap{}))
126 assert.Nil(t, nilPtr.Remove("key1"))
127 assert.Equal(t, ValueMap{}, nilPtr.Build())
128 }
129
130 func TestValueMapGetByKey(t *testing.T) {
131 item0 := String("a")
132 item1 := Int(1)
133 m := ValueMapBuild().Set("item0", item0).Set("item1", item1).Build()
134
135 assert.Equal(t, item0, m.Get("item0"))
136 assert.Equal(t, item1, m.Get("item1"))
137 assert.Equal(t, Null(), m.Get("bad-key"))
138
139 item, ok := m.TryGet("item0")
140 assert.True(t, ok)
141 assert.Equal(t, item0, item)
142 item, ok = m.TryGet("bad-key")
143 assert.False(t, ok)
144 assert.Equal(t, Null(), item)
145 }
146
147 func TestConvertValueMapToArbitraryValues(t *testing.T) {
148 m := ValueMapBuild().Set("x", ArrayOf(Int(2))).Build()
149 expected := map[string]interface{}{"x": []interface{}{float64(2)}}
150 assert.Equal(t, expected, m.AsArbitraryValueMap())
151 }
152
153 func TestConvertValueMapFromArbitraryValuesAndBackAgain(t *testing.T) {
154 mapValue0 := map[string]interface{}{"x": []interface{}{"b"}}
155 m := CopyArbitraryValueMap(mapValue0)
156 mapValue1 := m.AsArbitraryValueMap()
157 assert.Equal(t, mapValue0, mapValue1)
158
159 mapValue0["x"].([]interface{})[0] = "c"
160 assert.NotEqual(t, mapValue0, mapValue1)
161 }
162
163 func TestValueMapEqual(t *testing.T) {
164 valueFns := []func() ValueMap{
165 func() ValueMap { return ValueMap{} },
166 func() ValueMap { return ValueMapBuild().Build() },
167 func() ValueMap { return ValueMapBuild().Set("a", Int(1)).Build() },
168 func() ValueMap { return ValueMapBuild().Set("a", Int(2)).Build() },
169 func() ValueMap { return ValueMapBuild().Set("a", Int(1)).Set("b", Int(1)).Build() },
170 }
171 for i, fn0 := range valueFns {
172 v0 := fn0()
173 for j, fn1 := range valueFns {
174 v1 := fn1()
175 if i == j {
176 assert.True(t, v0.Equal(v1), "%s should equal %s", v0, v1)
177 assert.True(t, v0.Equal(v1), "%s should equal %s conversely", v1, v0)
178 } else {
179 assert.False(t, v0.Equal(v1), "%s should not equal %s", v0, v1)
180 assert.False(t, v1.Equal(v0), "%s should not equal %s", v1, v0)
181 }
182 }
183 }
184 }
185
186 func TestValueMapKeys(t *testing.T) {
187 assert.Nil(t, ValueMap{}.Keys(nil))
188 assert.Nil(t, ValueMapBuild().Build().Keys(nil))
189
190 m := ValueMapBuild().Set("a", Int(1)).Build()
191
192 assert.Equal(t, []string{"a"}, m.Keys(nil))
193 slice1 := []string{"x", "y", "z"}
194 assert.Equal(t, []string{"a"}, m.Keys(slice1))
195 assert.Equal(t, []string{"a", "y", "z"}, slice1)
196 slice2 := []string{}
197 assert.Equal(t, []string{"a"}, m.Keys(slice2))
198
199 m1 := ValueMapBuild().Set("a", Int(1)).Set("b", Int(2)).Set("c", Int(3)).Build()
200 keys := m1.Keys(nil)
201 sort.Strings(keys)
202 assert.Equal(t, []string{"a", "b", "c"}, keys)
203 }
204
205 func TestValueMapAsValue(t *testing.T) {
206 assert.Equal(t, Null(), ValueMap{}.AsValue())
207
208 m := ValueMapBuild().Set("a", Int(1)).Set("b", Int(2)).Build()
209 v := m.AsValue()
210 assert.Equal(t, ObjectBuild().Set("a", Int(1)).Set("b", Int(2)).Build(), v)
211 shouldBeSameMap(t, m.data, v.objectValue.data)
212 }
213
214 func TestValueMapAsMap(t *testing.T) {
215 assert.Nil(t, ValueMap{}.AsMap())
216
217 m := ValueMapBuild().Set("a", Bool(false)).Set("b", Bool(true)).Build()
218 mm := m.AsMap()
219 assert.Equal(t, map[string]Value{"a": Bool(false), "b": Bool(true)}, mm)
220 shouldNotBeSameMap(t, m.data, mm)
221 }
222
223 func TestValueMapAsArbitraryValueMap(t *testing.T) {
224 assert.Nil(t, ValueMap{}.AsArbitraryValueMap())
225
226 m := ValueMapBuild().Set("a", Bool(false)).Set("b", Bool(true)).Build()
227 mm := m.AsArbitraryValueMap()
228 assert.Equal(t, map[string]interface{}{"a": false, "b": true}, mm)
229 }
230
231 func TestTransformValueMap(t *testing.T) {
232 fnNoChanges := func(key string, value Value) (string, Value, bool) {
233 return key, value, true
234 }
235 fnAbsoluteValuesAndNoOddNumbers := func(key string, value Value) (string, Value, bool) {
236 if value.IntValue()%2 == 1 {
237 return key, value, false
238 }
239 if value.IntValue() < 0 {
240 return key, Int(-value.IntValue()), true
241 }
242 return key, value, true
243 }
244 fnTransformUsingKey := func(key string, value Value) (string, Value, bool) {
245 return key, String(fmt.Sprintf("%s=%s", key, value.JSONString())), true
246 }
247
248 m1 := ValueMapBuild().Set("a", Int(2)).Set("b", Int(4)).Set("c", Int(6)).Build()
249 m1a := m1.Transform(fnNoChanges)
250 m1b := m1.Transform(fnAbsoluteValuesAndNoOddNumbers)
251
252 assert.Equal(t, m1, m1a)
253 assert.Equal(t, m1, m1b)
254
255 m1.data["a"] = Int(0)
256 assert.Equal(t, m1, m1a)
257 assert.Equal(t, m1, m1b)
258
259 m2 := ValueMapBuild().Set("a", Int(2)).Set("b", Int(4)).Set("c", Int(1)).Set("d", Int(-6)).Build()
260 m2a := m2.Transform(fnNoChanges)
261 m2b := m2.Transform(fnAbsoluteValuesAndNoOddNumbers)
262
263 assert.Equal(t, m2, m2a)
264 m2.data["a"] = Int(0)
265 assert.Equal(t, m2, m2a)
266
267 assert.Equal(t, ValueMapBuild().Set("a", Int(2)).Set("b", Int(4)).Set("d", Int(6)).Build(), m2b)
268
269
270 m3 := ValueMapBuild().Set("a", Int(1)).Build()
271 assert.Equal(t, ValueMapBuild().Build(), m3.Transform(fnAbsoluteValuesAndNoOddNumbers))
272
273
274 m4 := ValueMapBuild().Set("a", Int(2)).Set("b", Int(4)).Build()
275 assert.Equal(t, ValueMapBuild().Set("a", String("a=2")).Set("b", String("b=4")).Build(),
276 m4.Transform(fnTransformUsingKey))
277
278
279
280 n := 0
281 fnTransformUsingKeyButNotFirst := func(key string, value Value) (string, Value, bool) {
282 n++
283 if n > 1 {
284 return fnTransformUsingKey(key, value)
285 }
286 return key, value, true
287 }
288 m5 := m4.Transform(fnTransformUsingKeyButNotFirst)
289 assert.NotEqual(t, m4, m5)
290 assert.Equal(t, m4.Count(), m5.Count())
291 if m5.Get("a").IsNumber() {
292 assert.Equal(t, Int(2), m5.Get("a"))
293 assert.Equal(t, String("b=4"), m5.Get("b"))
294 } else {
295 assert.Equal(t, String("a=2"), m5.Get("a"))
296 assert.Equal(t, Int(4), m5.Get("b"))
297 }
298
299 shouldNotCallThis := func(key string, value Value) (string, Value, bool) {
300 assert.Fail(t, "should not have called function")
301 return key, value, true
302 }
303 assert.Equal(t, ValueMap{}, ValueMap{}.Transform(shouldNotCallThis))
304 assert.Equal(t, ValueMapBuild().Build(), ValueMapBuild().Build().Transform(shouldNotCallThis))
305 }
306
307 func shouldBeSameMap(t *testing.T, m0 map[string]Value, m1 map[string]Value) {
308 m0["temp-property"] = Bool(true)
309 assert.Equal(t, m0, m1, "ValueMaps should be sharing same map but it was copied instead")
310 delete(m0, "temp-property")
311 }
312
313 func shouldNotBeSameMap(t *testing.T, m0 map[string]Value, m1 map[string]Value) {
314 m0["temp-property"] = Bool(true)
315 assert.NotEqual(t, m0, m1, "ValueMaps should not be sharing same map but they are")
316 delete(m0, "temp-property")
317 }
318
View as plain text