1 package funk
2
3 import (
4 "database/sql"
5 "fmt"
6 "reflect"
7 "testing"
8
9 "github.com/stretchr/testify/assert"
10 "github.com/stretchr/testify/require"
11 )
12
13 func TestMap(t *testing.T) {
14 is := assert.New(t)
15
16 r := Map([]int{1, 2, 3, 4}, func(x int) string {
17 return "Hello"
18 })
19
20 result, ok := r.([]string)
21
22 is.True(ok)
23 is.Equal(len(result), 4)
24
25 r = Map([]int{1, 2, 3, 4}, func(x int) (int, int) {
26 return x, x
27 })
28
29 resultType := reflect.TypeOf(r)
30
31 is.True(resultType.Kind() == reflect.Map)
32 is.True(resultType.Key().Kind() == reflect.Int)
33 is.True(resultType.Elem().Kind() == reflect.Int)
34
35 mapping := map[int]string{
36 1: "Florent",
37 2: "Gilles",
38 }
39
40 r = Map(mapping, func(k int, v string) int {
41 return k
42 })
43
44 is.True(reflect.TypeOf(r).Kind() == reflect.Slice)
45 is.True(reflect.TypeOf(r).Elem().Kind() == reflect.Int)
46
47 r = Map(mapping, func(k int, v string) (string, string) {
48 return fmt.Sprintf("%d", k), v
49 })
50
51 resultType = reflect.TypeOf(r)
52
53 is.True(resultType.Kind() == reflect.Map)
54 is.True(resultType.Key().Kind() == reflect.String)
55 is.True(resultType.Elem().Kind() == reflect.String)
56 }
57
58 func TestFlatMap(t *testing.T) {
59
60 is := assert.New(t)
61
62 x := reflect.Value{}.IsValid()
63 fmt.Println(x)
64
65 r := FlatMap([][]int{{1}, {2}, {3}, {4}}, func(x []int) []int {
66 return x
67 })
68
69 result, ok := r.([]int)
70
71 is.True(ok)
72 is.ElementsMatch(result, []int{1, 2, 3, 4})
73
74 mapping := map[string][]int{
75 "a": {1},
76 "b": {2},
77 }
78
79 r = FlatMap(mapping, func(k string, v []int) []int {
80 return v
81 })
82
83 result, ok = r.([]int)
84
85 is.True(ok)
86 is.ElementsMatch(result, []int{1, 2})
87 }
88
89 func TestToMap(t *testing.T) {
90 is := assert.New(t)
91
92 f := &Foo{
93 ID: 1,
94 FirstName: "Dark",
95 LastName: "Vador",
96 Age: 30,
97 Bar: &Bar{
98 Name: "Test",
99 },
100 }
101
102 results := []*Foo{f}
103
104 instanceMap := ToMap(results, "ID")
105
106 is.True(reflect.TypeOf(instanceMap).Kind() == reflect.Map)
107
108 mapping, ok := instanceMap.(map[int]*Foo)
109
110 is.True(ok)
111
112 for _, result := range results {
113 item, ok := mapping[result.ID]
114
115 is.True(ok)
116 is.True(reflect.TypeOf(item).Kind() == reflect.Ptr)
117 is.True(reflect.TypeOf(item).Elem().Kind() == reflect.Struct)
118
119 is.Equal(item.ID, result.ID)
120 }
121 }
122
123 func TestChunk(t *testing.T) {
124 is := assert.New(t)
125
126 results := Chunk([]int{0, 1, 2, 3, 4}, 2).([][]int)
127
128 is.Len(results, 3)
129 is.Len(results[0], 2)
130 is.Len(results[1], 2)
131 is.Len(results[2], 1)
132
133 is.Len(Chunk([]int{}, 2), 0)
134 is.Len(Chunk([]int{1}, 2), 1)
135 is.Len(Chunk([]int{1, 2, 3}, 0), 3)
136 }
137
138 func TestFlatten(t *testing.T) {
139 is := assert.New(t)
140
141 is.Equal(Flatten([][][]int{{{1, 2}}, {{3, 4}}}), [][]int{{1, 2}, {3, 4}})
142 }
143
144 func TestFlattenDeep(t *testing.T) {
145 is := assert.New(t)
146
147 is.Equal(FlattenDeep([][][]int{{{1, 2}}, {{3, 4}}}), []int{1, 2, 3, 4})
148 }
149
150 func TestShuffle(t *testing.T) {
151 initial := []int{0, 1, 2, 3, 4}
152
153 results := Shuffle(initial)
154
155 is := assert.New(t)
156
157 is.Len(results, 5)
158
159 for _, entry := range initial {
160 is.True(Contains(results, entry))
161 }
162 }
163
164 func TestReverse(t *testing.T) {
165 results := Reverse([]int{0, 1, 2, 3, 4})
166
167 is := assert.New(t)
168
169 is.Equal(Reverse("abcdefg"), "gfedcba")
170 is.Len(results, 5)
171
172 is.Equal(results, []int{4, 3, 2, 1, 0})
173 }
174
175 func TestUniq(t *testing.T) {
176 is := assert.New(t)
177
178 results := Uniq([]int{0, 1, 1, 2, 3, 0, 0, 12})
179 is.Len(results, 5)
180 is.Equal(results, []int{0, 1, 2, 3, 12})
181
182 results = Uniq([]string{"foo", "bar", "foo", "bar", "bar"})
183 is.Len(results, 2)
184 is.Equal(results, []string{"foo", "bar"})
185 }
186
187 func TestConvertSlice(t *testing.T) {
188 instances := []*Foo{foo, foo2}
189
190 var raw []Model
191
192 ConvertSlice(instances, &raw)
193
194 is := assert.New(t)
195
196 is.Len(raw, len(instances))
197 }
198
199 func TestDrop(t *testing.T) {
200 results := Drop([]int{0, 1, 1, 2, 3, 0, 0, 12}, 3)
201
202 is := assert.New(t)
203
204 is.Len(results, 5)
205
206 is.Equal([]int{2, 3, 0, 0, 12}, results)
207 }
208
209 func TestPrune(t *testing.T) {
210
211 var testCases = []struct {
212 OriginalFoo *Foo
213 Paths []string
214 ExpectedFoo *Foo
215 }{
216 {
217 foo,
218 []string{"FirstName"},
219 &Foo{
220 FirstName: foo.FirstName,
221 },
222 },
223 {
224 foo,
225 []string{"FirstName", "ID"},
226 &Foo{
227 FirstName: foo.FirstName,
228 ID: foo.ID,
229 },
230 },
231 {
232 foo,
233 []string{"EmptyValue.Int64"},
234 &Foo{
235 EmptyValue: sql.NullInt64{
236 Int64: foo.EmptyValue.Int64,
237 },
238 },
239 },
240 {
241 foo,
242 []string{"FirstName", "ID", "EmptyValue.Int64"},
243 &Foo{
244 FirstName: foo.FirstName,
245 ID: foo.ID,
246 EmptyValue: sql.NullInt64{
247 Int64: foo.EmptyValue.Int64,
248 },
249 },
250 },
251 {
252 foo,
253 []string{"FirstName", "ID", "EmptyValue.Int64"},
254 &Foo{
255 FirstName: foo.FirstName,
256 ID: foo.ID,
257 EmptyValue: sql.NullInt64{
258 Int64: foo.EmptyValue.Int64,
259 },
260 },
261 },
262 {
263 foo,
264 []string{"FirstName", "ID", "Bar"},
265 &Foo{
266 FirstName: foo.FirstName,
267 ID: foo.ID,
268 Bar: foo.Bar,
269 },
270 },
271 {
272 foo,
273 []string{"Bar", "Bars"},
274 &Foo{
275 Bar: foo.Bar,
276 Bars: foo.Bars,
277 },
278 },
279 {
280 foo,
281 []string{"FirstName", "Bars.Name"},
282 &Foo{
283 FirstName: foo.FirstName,
284 Bars: []*Bar{
285 {Name: bar.Name},
286 {Name: bar.Name},
287 },
288 },
289 },
290 {
291 foo,
292 []string{"Bars.Name", "Bars.Bars.Name"},
293 &Foo{
294 Bars: []*Bar{
295 {Name: bar.Name, Bars: []*Bar{{Name: "Level1-1"}, {Name: "Level1-2"}}},
296 {Name: bar.Name, Bars: []*Bar{{Name: "Level1-1"}, {Name: "Level1-2"}}},
297 },
298 },
299 },
300 {
301 foo,
302 []string{"BarInterface", "BarPointer"},
303 &Foo{
304 BarInterface: bar,
305 BarPointer: &bar,
306 },
307 },
308 }
309
310
311 for idx, tc := range testCases {
312 t.Run(fmt.Sprintf("Prune pointer test case #%v", idx), func(t *testing.T) {
313 is := assert.New(t)
314 res, err := Prune(tc.OriginalFoo, tc.Paths)
315 require.NoError(t, err)
316
317 fooPrune := res.(*Foo)
318 is.Equal(tc.ExpectedFoo, fooPrune)
319 })
320 }
321
322
323 for idx, tc := range testCases {
324 t.Run(fmt.Sprintf("Prune non pointer test case #%v", idx), func(t *testing.T) {
325 is := assert.New(t)
326 fooNonPtr := *tc.OriginalFoo
327 res, err := Prune(fooNonPtr, tc.Paths)
328 require.NoError(t, err)
329
330 fooPrune := res.(Foo)
331 is.Equal(*tc.ExpectedFoo, fooPrune)
332 })
333 }
334
335
336 var TagTestCases = []struct {
337 OriginalFoo *Foo
338 Paths []string
339 ExpectedFoo *Foo
340 Tag string
341 }{
342 {
343 foo,
344 []string{"tag 1", "tag 4.BarName"},
345 &Foo{
346 FirstName: foo.FirstName,
347 Bar: &Bar{
348 Name: bar.Name,
349 },
350 },
351 "tag_name",
352 },
353 }
354
355 for idx, tc := range TagTestCases {
356 t.Run(fmt.Sprintf("PruneByTag test case #%v", idx), func(t *testing.T) {
357 is := assert.New(t)
358 fooNonPtr := *tc.OriginalFoo
359 res, err := PruneByTag(fooNonPtr, tc.Paths, tc.Tag)
360 require.NoError(t, err)
361
362 fooPrune := res.(Foo)
363 is.Equal(*tc.ExpectedFoo, fooPrune)
364 })
365 }
366
367 t.Run("Bar Slice", func(t *testing.T) {
368 barSlice := []*Bar{bar, bar}
369 barSlicePruned, err := pruneByTag(barSlice, []string{"Name"}, nil )
370 require.NoError(t, err)
371 assert.Equal(t, []*Bar{{Name: bar.Name}, {Name: bar.Name}}, barSlicePruned)
372 })
373
374 t.Run("Bar Array", func(t *testing.T) {
375 barArr := [2]*Bar{bar, bar}
376 barArrPruned, err := pruneByTag(barArr, []string{"Name"}, nil )
377 require.NoError(t, err)
378 assert.Equal(t, [2]*Bar{{Name: bar.Name}, {Name: bar.Name}}, barArrPruned)
379 })
380
381
382
383 t.Run("Copy Value Str", func(t *testing.T) {
384 is := assert.New(t)
385 fooTest := &Foo{
386 Bar: &Bar{
387 Name: "bar",
388 },
389 }
390 res, err := pruneByTag(fooTest, []string{"Bar.Name"}, nil)
391 require.NoError(t, err)
392 fooTestPruned := res.(*Foo)
393 is.Equal(fooTest, fooTestPruned)
394
395
396 fooTestPruned.Bar.Name = "changed bar"
397
398 is.Equal(fooTest.Bar.Name, "bar")
399 })
400
401
402 var errCases = []struct {
403 InputFoo *Foo
404 Paths []string
405 TagName *string
406 }{
407 {
408 foo,
409 []string{"NotExist"},
410 nil,
411 },
412 {
413 foo,
414 []string{"FirstName.NotExist", "LastName"},
415 nil,
416 },
417 {
418 foo,
419 []string{"LastName", "FirstName.NotExist"},
420 nil,
421 },
422 {
423 foo,
424 []string{"LastName", "Bars.NotExist"},
425 nil,
426 },
427
428 {
429 foo,
430 []string{"tag 999"},
431 &[]string{"tag_name"}[0],
432 },
433 {
434 foo,
435 []string{"tag 1.NotExist"},
436 &[]string{"tag_name"}[0],
437 },
438 {
439 foo,
440 []string{"tag 4.NotExist"},
441 &[]string{"tag_name"}[0],
442 },
443 {
444 foo,
445 []string{"FirstName"},
446 &[]string{"tag_name_not_exist"}[0],
447 },
448 }
449
450 for idx, errTC := range errCases {
451 t.Run(fmt.Sprintf("error test case #%v", idx), func(t *testing.T) {
452 _, err := pruneByTag(errTC.InputFoo, errTC.Paths, errTC.TagName)
453 assert.Error(t, err)
454 })
455 }
456 }
457
458 func ExamplePrune() {
459 type ExampleFoo struct {
460 ExampleFooPtr *ExampleFoo `json:"example_foo_ptr"`
461 Name string `json:"name"`
462 Number int `json:"number"`
463 }
464
465 exampleFoo := ExampleFoo{
466 ExampleFooPtr: &ExampleFoo{
467 Name: "ExampleFooPtr",
468 Number: 2,
469 },
470 Name: "ExampleFoo",
471 Number: 1,
472 }
473
474
475 res, _ := Prune(exampleFoo, []string{"ExampleFooPtr.Name", "Number"})
476 prunedFoo := res.(ExampleFoo)
477 fmt.Println(prunedFoo.ExampleFooPtr.Name)
478 fmt.Println(prunedFoo.ExampleFooPtr.Number)
479 fmt.Println(prunedFoo.Name)
480 fmt.Println(prunedFoo.Number)
481
482
483 res2, _ := PruneByTag(exampleFoo, []string{"example_foo_ptr.name", "number"}, "json")
484 prunedByTagFoo := res2.(ExampleFoo)
485 fmt.Println(prunedByTagFoo.ExampleFooPtr.Name)
486 fmt.Println(prunedByTagFoo.ExampleFooPtr.Number)
487 fmt.Println(prunedByTagFoo.Name)
488 fmt.Println(prunedByTagFoo.Number)
489
490
491
492
493
494
495
496
497
498 }
499
View as plain text