1 package funk
2
3 import (
4 "database/sql"
5 "fmt"
6 "testing"
7
8 "github.com/stretchr/testify/assert"
9 )
10
11 func TestSet_EmptyPath(t *testing.T) {
12
13 var testCases = []struct {
14
15 Original interface{}
16 SetVal interface{}
17 }{
18
19 {
20 Original: 100,
21 SetVal: 1,
22 },
23
24 {
25 Original: "",
26 SetVal: "val",
27 },
28
29 {
30 Original: Bar{Name: "bar"},
31 SetVal: Bar{Name: "val"},
32 },
33
34 {
35 Original: []Bar{{Name: "bar"}},
36 SetVal: []Bar{{Name: "val1"}, {Name: "val2"}},
37 },
38 }
39
40 for idx, tc := range testCases {
41 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
42 is := assert.New(t)
43
44
45 err := Set(&tc.Original, tc.SetVal, "")
46 is.NoError(err)
47 is.Equal(tc.Original, tc.SetVal)
48 })
49 }
50 }
51
52 func TestSet_StructBasicOneLevel(t *testing.T) {
53 is := assert.New(t)
54
55 baz := Foo{
56 ID: 100,
57 FirstName: "firstname",
58 LastName: "lastname",
59 Age: 23,
60 Bar: &Bar{Name: "bar"},
61 Bars: []*Bar{{Name: "1"}},
62 EmptyValue: sql.NullInt64{
63 Int64: 64,
64 Valid: false,
65 },
66 }
67 expected := Foo{
68 ID: 1,
69 FirstName: "firstname1",
70 LastName: "lastname1",
71 Age: 24,
72 Bar: &Bar{Name: "b1", Bar: &Bar{Name: "b2"}},
73 Bars: []*Bar{{Name: "1"}, {Name: "2"}},
74 EmptyValue: sql.NullInt64{
75 Int64: 11,
76 Valid: true,
77 },
78 }
79 err := Set(&baz, 1, "ID")
80 is.NoError(err)
81 err = Set(&baz, expected.FirstName, "FirstName")
82 is.NoError(err)
83 err = Set(&baz, expected.LastName, "LastName")
84 is.NoError(err)
85 err = Set(&baz, expected.Age, "Age")
86 is.NoError(err)
87 err = Set(&baz, expected.Bar, "Bar")
88 is.NoError(err)
89 err = Set(&baz, expected.Bars, "Bars")
90 is.NoError(err)
91 err = Set(&baz, expected.EmptyValue, "EmptyValue")
92 is.NoError(err)
93 is.Equal(baz, expected)
94 }
95
96 func TestSetStruct_MultiLevels(t *testing.T) {
97
98 var testCases = []struct {
99 Original Bar
100 Path string
101 SetVal interface{}
102 Expected Bar
103 }{
104
105 {
106 Original: Bar{
107 Name: "1",
108 Bar: &Bar{
109 Name: "2",
110 Bars: []*Bar{
111 {Name: "3-1", Bars: []*Bar{{Name: "4-1"}, {Name: "4-2"}, {Name: "4-3"}}},
112 {Name: "3-2", Bars: []*Bar{{Name: "4-1"}, {Name: "4-2"}}},
113 },
114 },
115 },
116 Path: "Bar.Bars.Bars.Name",
117 SetVal: "val",
118 Expected: Bar{
119 Name: "1",
120 Bar: &Bar{
121 Name: "2",
122 Bars: []*Bar{
123 {Name: "3-1", Bars: []*Bar{{Name: "val"}, {Name: "val"}, {Name: "val"}}},
124 {Name: "3-2", Bars: []*Bar{{Name: "val"}, {Name: "val"}}},
125 },
126 },
127 },
128 },
129
130 {
131 Original: Bar{
132 Name: "1",
133 Bar: nil,
134 },
135 Path: "Bar.Bar.Bar.Name",
136 SetVal: "val",
137 Expected: Bar{
138 Name: "1",
139 Bar: &Bar{
140 Name: "",
141 Bar: &Bar{
142 Bar: &Bar{
143 Name: "val",
144 },
145 },
146 },
147 },
148 },
149
150 {
151 Original: Bar{
152 Name: "1",
153 Bar: &Bar{
154 Name: "2",
155 Bars: []*Bar{
156 {Name: "3-1", Bars: []*Bar{{Name: "4-1"}, {Name: "4-2"}, {Name: "4-3"}}},
157 {Name: "3-2", Bars: []*Bar{{Name: "4-1"}, {Name: "4-2"}}},
158 },
159 },
160 },
161 Path: "Bar.Bars.Bars.Bar.Name",
162 SetVal: "val",
163 Expected: Bar{
164 Name: "1",
165 Bar: &Bar{
166 Name: "2",
167 Bars: []*Bar{
168 {Name: "3-1", Bars: []*Bar{{Name: "4-1", Bar: &Bar{Name: "val"}},
169 {Name: "4-2", Bar: &Bar{Name: "val"}}, {Name: "4-3", Bar: &Bar{Name: "val"}}}},
170 {Name: "3-2", Bars: []*Bar{{Name: "4-1", Bar: &Bar{Name: "val"}}, {Name: "4-2", Bar: &Bar{Name: "val"}}}},
171 },
172 },
173 },
174 },
175 }
176
177 for idx, tc := range testCases {
178 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
179 is := assert.New(t)
180
181 err := Set(&tc.Original, tc.SetVal, tc.Path)
182 is.NoError(err)
183 is.Equal(tc.Expected, tc.Original)
184 })
185 }
186 }
187
188 func TestSet_StructWithCyclicStruct(t *testing.T) {
189 is := assert.New(t)
190
191 testBar := Bar{
192 Name: "testBar",
193 Bar: nil,
194 }
195 testBar.Bar = &testBar
196
197 err := Set(&testBar, "val", "Bar.Bar.Name")
198 is.NoError(err)
199 is.Equal("val", testBar.Name)
200 }
201
202 func TestSet_StructWithFieldNotInitialized(t *testing.T) {
203 is := assert.New(t)
204 myFoo := &Foo{
205 Bar: nil,
206 }
207 err := Set(myFoo, "name", "Bar.Name")
208 is.NoError(err)
209 is.Equal("name", myFoo.Bar.Name)
210 }
211
212 func TestSet_SlicePassByPtr(t *testing.T) {
213
214 var testCases = []struct {
215 Original interface{}
216 Path string
217 SetVal interface{}
218 Expected interface{}
219 }{
220
221 {
222 Original: []*Bar{},
223 Path: "",
224 SetVal: []*Bar{{Name: "bar"}},
225 Expected: []*Bar{{Name: "bar"}},
226 },
227
228 {
229 Original: []*Bar{},
230 Path: "Name",
231 SetVal: "val",
232 Expected: []*Bar{},
233 },
234
235 {
236 Original: []*Bar{{Name: "a"}, {Name: "b"}},
237 Path: "Name",
238 SetVal: "val",
239 Expected: []*Bar{{Name: "val"}, {Name: "val"}},
240 },
241
242 {
243 Original: []Bar{{Name: "a"}, {Name: "b"}},
244 Path: "Name",
245 SetVal: "val",
246 Expected: []Bar{{Name: "val"}, {Name: "val"}},
247 },
248
249 {
250 Original: []*Bar{nil, nil},
251 Path: "Name",
252 SetVal: "val",
253 Expected: []*Bar{{Name: "val"}, {Name: "val"}},
254 },
255
256 {
257 Original: []*Bar{{Name: "bar"}, nil},
258 Path: "Name",
259 SetVal: "val",
260 Expected: []*Bar{{Name: "val"}, {Name: "val"}},
261 },
262 }
263
264 for idx, tc := range testCases {
265 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
266 is := assert.New(t)
267
268 err := Set(&tc.Original, tc.SetVal, tc.Path)
269 is.NoError(err)
270 is.Equal(tc.Expected, tc.Original)
271 })
272 }
273 }
274
275 func TestSet_SlicePassDirectly(t *testing.T) {
276 var testCases = []struct {
277 Original interface{}
278 Path string
279 SetVal interface{}
280 Expected interface{}
281 }{
282
283
284
285 {
286 Original: []*Bar{},
287 Path: "Name",
288 SetVal: "val",
289 Expected: []*Bar{},
290 },
291
292 {
293 Original: []*Bar{{Name: "a"}, {Name: "b"}},
294 Path: "Name",
295 SetVal: "val",
296 Expected: []*Bar{{Name: "val"}, {Name: "val"}},
297 },
298
299 {
300 Original: []Bar{{Name: "a"}, {Name: "b"}},
301 Path: "Name",
302 SetVal: "val",
303 Expected: []Bar{{Name: "val"}, {Name: "val"}},
304 },
305
306 {
307 Original: []*Bar{nil, nil},
308 Path: "Name",
309 SetVal: "val",
310 Expected: []*Bar{{Name: "val"}, {Name: "val"}},
311 },
312
313 {
314 Original: []*Bar{{Name: "bar"}, nil},
315 Path: "Name",
316 SetVal: "val",
317 Expected: []*Bar{{Name: "val"}, {Name: "val"}},
318 },
319 }
320
321 for idx, tc := range testCases {
322 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
323 is := assert.New(t)
324
325 err := Set(tc.Original, tc.SetVal, tc.Path)
326 is.NoError(err)
327 is.Equal(tc.Expected, tc.Original)
328 })
329 }
330 }
331
332 func TestInterface(t *testing.T) {
333
334 var testCases = []struct {
335 OriginalFoo Foo
336 Path string
337 SetVal interface{}
338 ExpectedFoo Foo
339 }{
340
341 {
342 Foo{FirstName: ""},
343 "FirstName",
344 "hi",
345 Foo{FirstName: "hi"},
346 },
347
348 {
349 Foo{FirstName: "", GeneralInterface: nil},
350 "GeneralInterface",
351 "str",
352 Foo{FirstName: "", GeneralInterface: "str"},
353 },
354
355
356
357 {
358 Foo{FirstName: "", GeneralInterface: &Foo{FirstName: ""}},
359 "GeneralInterface.FirstName",
360 "foo",
361 Foo{FirstName: "", GeneralInterface: &Foo{FirstName: "foo"}},
362 },
363
364 {
365 Foo{FirstName: "", GeneralInterface: &Foo{GeneralInterface: nil}},
366 "GeneralInterface.GeneralInterface",
367 "val",
368 Foo{FirstName: "", GeneralInterface: &Foo{GeneralInterface: "val"}},
369 },
370 }
371
372 for idx, tc := range testCases {
373 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
374 is := assert.New(t)
375
376 err := Set(&tc.OriginalFoo, tc.SetVal, tc.Path)
377 is.NoError(err)
378 is.Equal(tc.ExpectedFoo, tc.OriginalFoo)
379 })
380 }
381
382 }
383
384 func TestSet_ErrorCaces(t *testing.T) {
385
386 var testCases = []struct {
387 OriginalFoo Foo
388 Path string
389 SetVal interface{}
390 }{
391
392
393 {
394 Foo{BarInterface: nil},
395 "BarInterface.Name",
396 "val",
397 },
398 {
399 Foo{GeneralInterface: &Foo{BarInterface: nil}},
400 "GeneralInterface.BarInterface.Name",
401 "val",
402 },
403
404 {
405 Foo{FirstName: ""},
406 "FirstName",
407 20,
408 },
409 }
410
411 for idx, tc := range testCases {
412 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
413 is := assert.New(t)
414
415 err := Set(&tc.OriginalFoo, tc.SetVal, tc.Path)
416 is.Error(err)
417 })
418 }
419
420 t.Run("not pointer", func(t *testing.T) {
421 is := assert.New(t)
422 baz := Bar{Name: "dummy"}
423 err := Set(baz, Bar{Name: "dummy2"}, "Name")
424 is.Error(err)
425 })
426
427 t.Run("Unexported field", func(t *testing.T) {
428 is := assert.New(t)
429 s := struct {
430 name string
431 }{name: "dummy"}
432 err := Set(&s, s, "name")
433 is.Error(err)
434 })
435 }
436
437 func TestMustSet_Basic(t *testing.T) {
438 t.Run("Variable", func(t *testing.T) {
439 is := assert.New(t)
440 s := 1
441 MustSet(&s, 2, "")
442 is.Equal(2, s)
443 })
444
445 t.Run("Struct", func(t *testing.T) {
446 is := assert.New(t)
447 s := Bar{Name: "a"}
448 MustSet(&s, "b", "Name")
449 is.Equal("b", s.Name)
450 })
451 }
452
453
454
455 func ExampleSet() {
456
457 var bar Bar = Bar{
458 Name: "level-0",
459 Bar: &Bar{
460 Name: "level-1",
461 Bars: []*Bar{
462 {Name: "level2-1"},
463 {Name: "level2-2"},
464 },
465 },
466 }
467
468 _ = Set(&bar, "level-0-new", "Name")
469 fmt.Println(bar.Name)
470
471
472 MustSet(&bar, "level-1-new", "Bar.Name")
473 fmt.Println(bar.Bar.Name)
474
475 _ = Set(&bar, "level-2-new", "Bar.Bars.Name")
476 fmt.Println(bar.Bar.Bars[0].Name)
477 fmt.Println(bar.Bar.Bars[1].Name)
478
479
480
481
482
483
484 }
485
View as plain text