1 package funk
2
3 import (
4 "fmt"
5 "reflect"
6 "testing"
7
8 "github.com/stretchr/testify/assert"
9 )
10
11 func TestChainChunk(t *testing.T) {
12 testCases := []struct {
13 In interface{}
14 Size int
15 }{
16 {In: []int{0, 1, 2, 3, 4}, Size: 2},
17 {In: []int{}, Size: 2},
18 {In: []int{1}, Size: 2},
19 }
20
21 for idx, tc := range testCases {
22 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
23 is := assert.New(t)
24
25 expected := Chunk(tc.In, tc.Size)
26 actual := Chain(tc.In).Chunk(tc.Size).Value()
27
28 is.Equal(expected, actual)
29 })
30 }
31 }
32
33 func TestChainCompact(t *testing.T) {
34 var emptyFunc func() bool
35 emptyFuncPtr := &emptyFunc
36
37 nonEmptyFunc := func() bool { return true }
38 nonEmptyFuncPtr := &nonEmptyFunc
39
40 nonEmptyMap := map[int]int{1: 2}
41 nonEmptyMapPtr := &nonEmptyMap
42
43 var emptyMap map[int]int
44 emptyMapPtr := &emptyMap
45
46 var emptyChan chan bool
47 nonEmptyChan := make(chan bool, 1)
48 nonEmptyChan <- true
49
50 emptyChanPtr := &emptyChan
51 nonEmptyChanPtr := &nonEmptyChan
52
53 var emptyString string
54 emptyStringPtr := &emptyString
55
56 nonEmptyString := "42"
57 nonEmptyStringPtr := &nonEmptyString
58
59 testCases := []struct {
60 In interface{}
61 }{
62 {In: []interface{}{42, nil, (*int)(nil)}},
63 {In: []interface{}{42, emptyFuncPtr, emptyFunc, nonEmptyFuncPtr}},
64 {In: []interface{}{42, [2]int{}, map[int]int{}, []string{}, nonEmptyMapPtr, emptyMap, emptyMapPtr, nonEmptyMap, nonEmptyChan, emptyChan, emptyChanPtr, nonEmptyChanPtr}},
65 {In: []interface{}{true, 0, float64(0), "", "42", emptyStringPtr, nonEmptyStringPtr, false}},
66 }
67
68 for idx, tc := range testCases {
69 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
70 is := assert.New(t)
71
72 expected := Compact(tc.In)
73 actual := Chain(tc.In).Compact().Value()
74
75 is.Equal(expected, actual)
76 })
77 }
78 }
79
80 func TestChainDrop(t *testing.T) {
81 testCases := []struct {
82 In interface{}
83 N int
84 }{
85 {In: []int{0, 1, 1, 2, 3, 0, 0, 12}, N: 3},
86
87
88
89 }
90
91 for idx, tc := range testCases {
92 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
93 is := assert.New(t)
94
95 expected := Drop(tc.In, tc.N)
96 actual := Chain(tc.In).Drop(tc.N).Value()
97
98 is.Equal(expected, actual)
99 })
100 }
101 }
102
103 func TestChainFilter(t *testing.T) {
104 testCases := []struct {
105 In interface{}
106 Predicate interface{}
107 }{
108 {
109 In: []int{1, 2, 3, 4},
110 Predicate: func(x int) bool { return x%2 == 0 },
111 },
112 }
113
114 for idx, tc := range testCases {
115 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
116 is := assert.New(t)
117
118 expected := Filter(tc.In, tc.Predicate)
119 actual := Chain(tc.In).Filter(tc.Predicate).Value()
120
121 is.Equal(expected, actual)
122 })
123 }
124 }
125 func TestChainFilter_SideEffect(t *testing.T) {
126 is := assert.New(t)
127
128 type foo struct {
129 bar string
130 }
131 in := []*foo{&foo{"foo"}, &foo{"bar"}}
132
133 chain := Chain(in)
134 is.Equal([]*foo{&foo{"foo"}, &foo{"bar"}}, chain.Value())
135
136 filtered := chain.Filter(func(x *foo) bool {
137 x.bar = "__" + x.bar + "__"
138 return x.bar == "foo"
139 })
140 is.Equal([]*foo{}, filtered.Value())
141
142
143 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, chain.Value())
144 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, in)
145 }
146
147 func TestChainFlatten(t *testing.T) {
148 testCases := []struct {
149 In interface{}
150 }{
151 {
152 In: [][]int{{1, 2}, {3, 4}},
153 },
154 {
155 In: [][][]int{{{1, 2}, {3, 4}}, {{5, 6}}},
156 },
157 }
158
159 for idx, tc := range testCases {
160 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
161 is := assert.New(t)
162
163 expected := Flatten(tc.In)
164 actual := Chain(tc.In).Flatten().Value()
165
166 is.Equal(expected, actual)
167 })
168 }
169 }
170
171 func TestChainFlattenDeep(t *testing.T) {
172 testCases := []struct {
173 In interface{}
174 }{
175 {
176 In: [][]int{{1, 2}, {3, 4}},
177 },
178 {
179 In: [][][]int{{{1, 2}, {3, 4}}, {{5, 6}}},
180 },
181 }
182
183 for idx, tc := range testCases {
184 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
185 is := assert.New(t)
186
187 expected := FlattenDeep(tc.In)
188 actual := Chain(tc.In).FlattenDeep().Value()
189
190 is.Equal(expected, actual)
191 })
192 }
193 }
194
195 func TestChainInitial(t *testing.T) {
196 testCases := []struct {
197 In interface{}
198 }{
199 {
200 In: []int{},
201 },
202 {
203 In: []int{0},
204 },
205 {
206 In: []int{0, 1, 2, 3},
207 },
208 }
209
210 for idx, tc := range testCases {
211 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
212 is := assert.New(t)
213
214 expected := Initial(tc.In)
215 actual := Chain(tc.In).Initial().Value()
216
217 is.Equal(expected, actual)
218 })
219 }
220 }
221
222 func TestChainIntersect(t *testing.T) {
223 testCases := []struct {
224 In interface{}
225 Sec interface{}
226 }{
227 {
228 In: []int{1, 2, 3, 4},
229 Sec: []int{2, 4, 6},
230 },
231 {
232 In: []string{"foo", "bar", "hello", "bar"},
233 Sec: []string{"foo", "bar"},
234 },
235 }
236
237 for idx, tc := range testCases {
238 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
239 is := assert.New(t)
240
241 expected := Intersect(tc.In, tc.Sec)
242 actual := Chain(tc.In).Intersect(tc.Sec).Value()
243
244 is.Equal(expected, actual)
245 })
246 }
247 }
248
249 func TestChainMap(t *testing.T) {
250 testCases := []struct {
251 In interface{}
252 MapFnc interface{}
253 }{
254 {
255 In: []int{1, 2, 3, 4},
256 MapFnc: func(x int) string { return "Hello" },
257 },
258 {
259 In: []int{1, 2, 3, 4},
260 MapFnc: func(x int) (int, int) { return x, x },
261 },
262 {
263 In: map[int]string{1: "Florent", 2: "Gilles"},
264 MapFnc: func(k int, v string) int { return k },
265 },
266 {
267 In: map[int]string{1: "Florent", 2: "Gilles"},
268 MapFnc: func(k int, v string) (string, string) { return fmt.Sprintf("%d", k), v },
269 },
270 }
271
272 for idx, tc := range testCases {
273 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
274 is := assert.New(t)
275
276 expected := Map(tc.In, tc.MapFnc)
277 actual := Chain(tc.In).Map(tc.MapFnc).Value()
278
279 if reflect.TypeOf(expected).Kind() == reflect.Map {
280 is.Equal(expected, actual)
281 } else {
282 is.ElementsMatch(expected, actual)
283 }
284 })
285 }
286 }
287
288 func TestChainFlatMap(t *testing.T) {
289 testCases := []struct {
290 In interface{}
291 FlatMapFnc interface{}
292 }{
293 {
294 In: [][]int{{1}, {2}, {3}, {4}},
295 FlatMapFnc: func(x []int) []int { return x },
296 },
297 {
298 In: map[string][]int{"Florent": {1}, "Gilles": {2}},
299 FlatMapFnc: func(k string, v []int) []int { return v },
300 },
301 }
302
303 for idx, tc := range testCases {
304 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
305 is := assert.New(t)
306
307 expected := FlatMap(tc.In, tc.FlatMapFnc)
308 actual := Chain(tc.In).FlatMap(tc.FlatMapFnc).Value()
309
310 is.ElementsMatch(expected, actual)
311 })
312 }
313 }
314
315 func TestChainMap_SideEffect(t *testing.T) {
316 is := assert.New(t)
317
318 type foo struct {
319 bar string
320 }
321 in := []*foo{&foo{"foo"}, &foo{"bar"}}
322
323 chain := Chain(in)
324 is.Equal([]*foo{&foo{"foo"}, &foo{"bar"}}, chain.Value())
325
326 mapped := chain.Map(func(x *foo) (string, bool) {
327 x.bar = "__" + x.bar + "__"
328 return x.bar, x.bar == "foo"
329 })
330 is.Equal(map[string]bool{"__foo__": false, "__bar__": false}, mapped.Value())
331
332
333 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, chain.Value())
334 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, in)
335 }
336
337 func TestChainReverse(t *testing.T) {
338 testCases := []struct {
339 In interface{}
340 }{
341 {
342 In: []int{0, 1, 2, 3, 4},
343 },
344 {
345 In: "abcdefg",
346 },
347 }
348
349 for idx, tc := range testCases {
350 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
351 is := assert.New(t)
352
353 expected := Reverse(tc.In)
354 actual := Chain(tc.In).Reverse().Value()
355
356 is.Equal(expected, actual)
357 })
358 }
359 }
360
361 func TestChainShuffle(t *testing.T) {
362 testCases := []struct {
363 In interface{}
364 }{
365 {
366 In: []int{0, 1, 2, 3, 4},
367 },
368 }
369
370 for idx, tc := range testCases {
371 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
372 is := assert.New(t)
373
374 expected := Shuffle(tc.In)
375 actual := Chain(tc.In).Shuffle().Value()
376
377 is.NotEqual(expected, actual)
378 is.ElementsMatch(expected, actual)
379 })
380 }
381 }
382
383 func TestChainTail(t *testing.T) {
384 testCases := []struct {
385 In interface{}
386 }{
387 {
388 In: []int{},
389 },
390 {
391 In: []int{0},
392 },
393 {
394 In: []int{0, 1, 2, 3},
395 },
396 }
397
398 for idx, tc := range testCases {
399 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
400 is := assert.New(t)
401
402 expected := Tail(tc.In)
403 actual := Chain(tc.In).Tail().Value()
404
405 is.Equal(expected, actual)
406 })
407 }
408 }
409
410 func TestChainUniq(t *testing.T) {
411 testCases := []struct {
412 In interface{}
413 }{
414 {
415 In: []int{0, 1, 1, 2, 3, 0, 0, 12},
416 },
417 }
418
419 for idx, tc := range testCases {
420 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
421 is := assert.New(t)
422
423 expected := Uniq(tc.In)
424 actual := Chain(tc.In).Uniq().Value()
425
426 is.Equal(expected, actual)
427 })
428 }
429 }
430
431 func TestChainAll(t *testing.T) {
432 testCases := []struct {
433 In []interface{}
434 }{
435 {In: []interface{}{"foo", "bar"}},
436 {In: []interface{}{"foo", ""}},
437 {In: []interface{}{"", ""}},
438 {In: []interface{}{}},
439 {In: []interface{}{true, "foo", 6}},
440 {In: []interface{}{true, "", 6}},
441 {In: []interface{}{true, "foo", 0}},
442 {In: []interface{}{false, "foo", 6}},
443 {In: []interface{}{false, "", 0}},
444 }
445
446 for idx, tc := range testCases {
447 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
448 is := assert.New(t)
449
450 expected := All(tc.In...)
451 actual := Chain(tc.In).All()
452
453 is.Equal(expected, actual)
454 })
455 }
456 }
457
458 func TestChainAny(t *testing.T) {
459 testCases := []struct {
460 In []interface{}
461 }{
462 {In: []interface{}{"foo", "bar"}},
463 {In: []interface{}{"foo", ""}},
464 {In: []interface{}{"", ""}},
465 {In: []interface{}{}},
466 {In: []interface{}{true, "foo", 6}},
467 {In: []interface{}{true, "", 6}},
468 {In: []interface{}{true, "foo", 0}},
469 {In: []interface{}{false, "foo", 6}},
470 {In: []interface{}{false, "", 0}},
471 }
472
473 for idx, tc := range testCases {
474 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
475 is := assert.New(t)
476
477 expected := Any(tc.In...)
478 actual := Chain(tc.In).Any()
479
480 is.Equal(expected, actual)
481 })
482 }
483 }
484
485 func TestChainContains(t *testing.T) {
486 testCases := []struct {
487 In interface{}
488 Contains interface{}
489 }{
490 {
491 In: []string{"foo", "bar"},
492 Contains: "bar",
493 },
494 {
495 In: []string{"foo", "bar"},
496 Contains: func (value string) bool {
497 return value == "bar"
498 },
499 },
500 {
501 In: results,
502 Contains: f,
503 },
504 {
505 In: results,
506 Contains: nil,
507 },
508 {
509 In: results,
510 Contains: b,
511 },
512 {
513 In: "florent",
514 Contains: "rent",
515 },
516 {
517 In: "florent",
518 Contains: "gilles",
519 },
520 {
521 In: map[int]*Foo{1: f, 3: c},
522 Contains: 1,
523 },
524 {
525 In: map[int]*Foo{1: f, 3: c},
526 Contains: 2,
527 },
528 {
529 In: map[int]*Foo{1: f, 3: c},
530 Contains: func (key int, foo *Foo) bool {
531 return key == 3 && foo.FirstName == "Harald"
532 },
533 },
534 }
535
536 for idx, tc := range testCases {
537 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
538 is := assert.New(t)
539
540 expected := Contains(tc.In, tc.Contains)
541 actual := Chain(tc.In).Contains(tc.Contains)
542
543 is.Equal(expected, actual)
544 })
545 }
546 }
547
548 func TestChainEvery(t *testing.T) {
549 testCases := []struct {
550 In interface{}
551 Contains []interface{}
552 }{
553 {
554 In: []string{"foo", "bar", "baz"},
555 Contains: []interface{}{"bar", "foo"},
556 },
557 {
558 In: results,
559 Contains: []interface{}{f, c},
560 },
561 {
562 In: results,
563 Contains: []interface{}{nil},
564 },
565 {
566 In: results,
567 Contains: []interface{}{f, b},
568 },
569 {
570 In: "florent",
571 Contains: []interface{}{"rent", "flo"},
572 },
573 {
574 In: "florent",
575 Contains: []interface{}{"rent", "gilles"},
576 },
577 {
578 In: map[int]*Foo{1: f, 3: c},
579 Contains: []interface{}{1, 3},
580 },
581 {
582 In: map[int]*Foo{1: f, 3: c},
583 Contains: []interface{}{2, 3},
584 },
585 }
586
587 for idx, tc := range testCases {
588 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
589 is := assert.New(t)
590
591 expected := Every(tc.In, tc.Contains...)
592 actual := Chain(tc.In).Every(tc.Contains...)
593
594 is.Equal(expected, actual)
595 })
596 }
597 }
598
599 func TestChainFind(t *testing.T) {
600 testCases := []struct {
601 In interface{}
602 Predicate interface{}
603 }{
604 {
605 In: []int{1, 2, 3, 4},
606 Predicate: func(x int) bool { return x%2 == 0 },
607 },
608 }
609
610 for idx, tc := range testCases {
611 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
612 is := assert.New(t)
613
614 expected := Find(tc.In, tc.Predicate)
615 actual := Chain(tc.In).Find(tc.Predicate)
616
617 is.Equal(expected, actual)
618 })
619 }
620 }
621
622 func TestChainFind_SideEffect(t *testing.T) {
623 is := assert.New(t)
624
625 type foo struct {
626 bar string
627 }
628 in := []*foo{&foo{"foo"}, &foo{"bar"}}
629
630 chain := Chain(in)
631 is.Equal([]*foo{&foo{"foo"}, &foo{"bar"}}, chain.Value())
632
633 result := chain.Find(func(x *foo) bool {
634 x.bar = "__" + x.bar + "__"
635 return x.bar == "foo"
636 })
637 is.Nil(result)
638
639
640 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, chain.Value())
641 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, in)
642 }
643
644 func TestChainForEach(t *testing.T) {
645 var expectedAcc, actualAcc []interface{}
646
647 testCases := []struct {
648 In interface{}
649 FunkIterator interface{}
650 ChainIterator interface{}
651 }{
652 {
653 In: []int{1, 2, 3, 4},
654 FunkIterator: func(x int) {
655 if x%2 == 0 {
656 expectedAcc = append(expectedAcc, x)
657 }
658 },
659 ChainIterator: func(x int) {
660 if x%2 == 0 {
661 actualAcc = append(actualAcc, x)
662 }
663 },
664 },
665 {
666 In: map[int]string{1: "Florent", 2: "Gilles"},
667 FunkIterator: func(k int, v string) { expectedAcc = append(expectedAcc, fmt.Sprintf("%d:%s", k, v)) },
668 ChainIterator: func(k int, v string) { actualAcc = append(actualAcc, fmt.Sprintf("%d:%s", k, v)) },
669 },
670 }
671
672 for idx, tc := range testCases {
673 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
674 is := assert.New(t)
675 expectedAcc = []interface{}{}
676 actualAcc = []interface{}{}
677
678 ForEach(tc.In, tc.FunkIterator)
679 Chain(tc.In).ForEach(tc.ChainIterator)
680
681 is.ElementsMatch(expectedAcc, actualAcc)
682 })
683 }
684 }
685
686 func TestChainForEach_SideEffect(t *testing.T) {
687 is := assert.New(t)
688
689 type foo struct {
690 bar string
691 }
692 var out []*foo
693 in := []*foo{&foo{"foo"}, &foo{"bar"}}
694
695 chain := Chain(in)
696 is.Equal([]*foo{&foo{"foo"}, &foo{"bar"}}, chain.Value())
697
698 chain.ForEach(func(x *foo) {
699 x.bar = "__" + x.bar + "__"
700 out = append(out, x)
701 })
702 is.Equal([]*foo{&foo{"__foo__"}, &foo{"__bar__"}}, out)
703
704
705 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, chain.Value())
706 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, in)
707 }
708
709 func TestChainForEachRight(t *testing.T) {
710 var expectedAcc, actualAcc []interface{}
711
712 testCases := []struct {
713 In interface{}
714 FunkIterator interface{}
715 ChainIterator interface{}
716 }{
717 {
718 In: []int{1, 2, 3, 4},
719 FunkIterator: func(x int) {
720 if x%2 == 0 {
721 expectedAcc = append(expectedAcc, x)
722 }
723 },
724 ChainIterator: func(x int) {
725 if x%2 == 0 {
726 actualAcc = append(actualAcc, x)
727 }
728 },
729 },
730 {
731 In: map[int]string{1: "Florent", 2: "Gilles"},
732 FunkIterator: func(k int, v string) { expectedAcc = append(expectedAcc, fmt.Sprintf("%d:%s", k, v)) },
733 ChainIterator: func(k int, v string) { actualAcc = append(actualAcc, fmt.Sprintf("%d:%s", k, v)) },
734 },
735 }
736
737 for idx, tc := range testCases {
738 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
739 is := assert.New(t)
740 expectedAcc = []interface{}{}
741 actualAcc = []interface{}{}
742
743 ForEachRight(tc.In, tc.FunkIterator)
744 Chain(tc.In).ForEachRight(tc.ChainIterator)
745
746 is.ElementsMatch(expectedAcc, actualAcc)
747 })
748 }
749 }
750
751 func TestChainForEachRight_SideEffect(t *testing.T) {
752 is := assert.New(t)
753
754 type foo struct {
755 bar string
756 }
757 var out []*foo
758 in := []*foo{&foo{"foo"}, &foo{"bar"}}
759
760 chain := Chain(in)
761 is.Equal([]*foo{&foo{"foo"}, &foo{"bar"}}, chain.Value())
762
763 chain.ForEachRight(func(x *foo) {
764 x.bar = "__" + x.bar + "__"
765 out = append(out, x)
766 })
767 is.Equal([]*foo{&foo{"__bar__"}, &foo{"__foo__"}}, out)
768
769
770 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, chain.Value())
771 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, in)
772 }
773
774 func TestChainHead(t *testing.T) {
775 testCases := []struct {
776 In interface{}
777 }{
778 {
779 In: []int{1, 2, 3, 4},
780 },
781 }
782
783 for idx, tc := range testCases {
784 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
785 is := assert.New(t)
786
787 expected := Head(tc.In)
788 actual := Chain(tc.In).Head()
789
790 is.Equal(expected, actual)
791 })
792 }
793 }
794
795 func TestChainKeys(t *testing.T) {
796 testCases := []struct {
797 In interface{}
798 }{
799 {In: map[string]int{"one": 1, "two": 2}},
800 {In: &map[string]int{"one": 1, "two": 2}},
801 {In: map[int]complex128{5: 1 + 8i, 3: 2}},
802 }
803
804 for idx, tc := range testCases {
805 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
806 is := assert.New(t)
807
808 expected := Keys(tc.In)
809 actual := Chain(tc.In).Keys()
810
811 is.ElementsMatch(expected, actual)
812 })
813 }
814 }
815
816 func TestChainIndexOf(t *testing.T) {
817 testCases := []struct {
818 In interface{}
819 Item interface{}
820 }{
821 {
822 In: []string{"foo", "bar"},
823 Item: "bar",
824 },
825 {
826 In: []string{"foo", "bar"},
827 Item: func (value string) bool {
828 return value == "bar"
829 },
830 },
831 {
832 In: results,
833 Item: f,
834 },
835 {
836 In: results,
837 Item: b,
838 },
839 }
840
841 for idx, tc := range testCases {
842 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
843 is := assert.New(t)
844
845 expected := IndexOf(tc.In, tc.Item)
846 actual := Chain(tc.In).IndexOf(tc.Item)
847
848 is.Equal(expected, actual)
849 })
850 }
851 }
852
853 func TestChainIsEmpty(t *testing.T) {
854 testCases := []struct {
855 In interface{}
856 }{
857 {In: ""},
858 {In: [0]interface{}{}},
859 {In: []interface{}(nil)},
860 {In: map[interface{}]interface{}(nil)},
861 {In: "s"},
862 {In: [1]interface{}{1}},
863 {In: []interface{}{}},
864 {In: map[interface{}]interface{}{}},
865 }
866
867 for idx, tc := range testCases {
868 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
869 is := assert.New(t)
870
871 expected := IsEmpty(tc.In)
872 actual := Chain(tc.In).IsEmpty()
873
874 is.Equal(expected, actual)
875 })
876 }
877 }
878
879 func TestChainLast(t *testing.T) {
880 testCases := []struct {
881 In interface{}
882 }{
883 {
884 In: []int{1, 2, 3, 4},
885 },
886 }
887
888 for idx, tc := range testCases {
889 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
890 is := assert.New(t)
891
892 expected := Last(tc.In)
893 actual := Chain(tc.In).Last()
894
895 is.Equal(expected, actual)
896 })
897 }
898 }
899
900 func TestChainLastIndexOf(t *testing.T) {
901 testCases := []struct {
902 In interface{}
903 Item interface{}
904 }{
905 {
906 In: []string{"foo", "bar", "bar"},
907 Item: "bar",
908 },
909 {
910 In: []string{"foo", "bar", "bar"},
911 Item: func (value string) bool {
912 return value == "bar"
913 },
914 },
915 {
916 In: []int{1, 2, 2, 3},
917 Item: 2,
918 },
919 {
920 In: []int{1, 2, 2, 3},
921 Item: 4,
922 },
923 }
924
925 for idx, tc := range testCases {
926 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
927 is := assert.New(t)
928
929 expected := LastIndexOf(tc.In, tc.Item)
930 actual := Chain(tc.In).LastIndexOf(tc.Item)
931
932 is.Equal(expected, actual)
933 })
934 }
935 }
936
937 func TestChainNotEmpty(t *testing.T) {
938 testCases := []struct {
939 In interface{}
940 }{
941 {In: ""},
942 {In: [0]interface{}{}},
943 {In: []interface{}(nil)},
944 {In: map[interface{}]interface{}(nil)},
945 {In: "s"},
946 {In: [1]interface{}{1}},
947 {In: []interface{}{}},
948 {In: map[interface{}]interface{}{}},
949 }
950
951 for idx, tc := range testCases {
952 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
953 is := assert.New(t)
954
955 expected := NotEmpty(tc.In)
956 actual := Chain(tc.In).NotEmpty()
957
958 is.Equal(expected, actual)
959 })
960 }
961 }
962
963 func TestChainProduct(t *testing.T) {
964 testCases := []struct {
965 In interface{}
966 }{
967 {In: []int{0, 1, 2, 3}},
968 {In: &[]int{0, 1, 2, 3}},
969 {In: []interface{}{1, 2, 3, 0.5}},
970 }
971
972 for idx, tc := range testCases {
973 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
974 is := assert.New(t)
975
976 expected := Product(tc.In)
977 actual := Chain(tc.In).Product()
978
979 is.Equal(expected, actual)
980 })
981 }
982 }
983
984 func TestChainReduce(t *testing.T) {
985 testCases := []struct {
986 In interface{}
987 ReduceFunc interface{}
988 Acc interface{}
989 }{
990 {
991 In: []int{1, 2, 3, 4},
992 ReduceFunc: func(acc, elem int) int { return acc + elem },
993 Acc: 0,
994 },
995 {
996 In: &[]int16{1, 2, 3, 4},
997 ReduceFunc: '+',
998 Acc: 5,
999 },
1000 {
1001 In: []float64{1.1, 2.2, 3.3},
1002 ReduceFunc: '+',
1003 Acc: 0,
1004 },
1005 {
1006 In: &[]int{1, 2, 3, 5},
1007 ReduceFunc: func(acc int8, elem int16) int32 { return int32(acc) * int32(elem) },
1008 Acc: 1,
1009 },
1010 {
1011 In: []interface{}{1, 2, 3.3, 4},
1012 ReduceFunc: '*',
1013 Acc: 1,
1014 },
1015 {
1016 In: []string{"1", "2", "3", "4"},
1017 ReduceFunc: func(acc string, elem string) string { return acc + elem },
1018 Acc: "",
1019 },
1020 }
1021
1022 for idx, tc := range testCases {
1023 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
1024 is := assert.New(t)
1025
1026 expected := Reduce(tc.In, tc.ReduceFunc, tc.Acc)
1027 actual := Chain(tc.In).Reduce(tc.ReduceFunc, tc.Acc)
1028
1029 is.Equal(expected, actual)
1030 })
1031 }
1032 }
1033
1034 func TestChainSum(t *testing.T) {
1035 testCases := []struct {
1036 In interface{}
1037 }{
1038 {In: []int{0, 1, 2, 3}},
1039 {In: &[]int{0, 1, 2, 3}},
1040 {In: []interface{}{1, 2, 3, 0.5}},
1041 }
1042
1043 for idx, tc := range testCases {
1044 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
1045 is := assert.New(t)
1046
1047 expected := Sum(tc.In)
1048 actual := Chain(tc.In).Sum()
1049
1050 is.Equal(expected, actual)
1051 })
1052 }
1053 }
1054
1055 func TestChainType(t *testing.T) {
1056 type key string
1057 var x key
1058
1059 testCases := []struct {
1060 In interface{}
1061 }{
1062 {In: []string{}},
1063 {In: []int{}},
1064 {In: []bool{}},
1065 {In: []interface{}{}},
1066 {In: &[]interface{}{}},
1067 {In: map[int]string{}},
1068 {In: map[complex128]int{}},
1069 {In: map[string]string{}},
1070 {In: map[int]interface{}{}},
1071 {In: map[key]interface{}{}},
1072 {In: &map[key]interface{}{}},
1073 {In: ""},
1074 {In: &x},
1075 }
1076
1077 for idx, tc := range testCases {
1078 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
1079 is := assert.New(t)
1080
1081 actual := Chain(tc.In).Type()
1082
1083 is.Equal(reflect.TypeOf(tc.In), actual)
1084 })
1085 }
1086 }
1087
1088 func TestChainValue(t *testing.T) {
1089 testCases := []struct {
1090 In interface{}
1091 }{
1092 {In: []int{0, 1, 2, 3}},
1093 {In: []string{"foo", "bar"}},
1094 {In: &[]string{"foo", "bar"}},
1095 {In: map[int]string{1: "foo", 2: "bar"}},
1096 {In: map[string]string{"foo": "foo", "bar": "bar"}},
1097 {In: &map[string]string{"foo": "foo", "bar": "bar"}},
1098 {In: "foo"},
1099 }
1100
1101 for idx, tc := range testCases {
1102 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
1103 is := assert.New(t)
1104
1105 actual := Chain(tc.In).Value()
1106
1107 is.Equal(tc.In, actual)
1108 })
1109 }
1110 }
1111
1112 func TestChainValues(t *testing.T) {
1113 testCases := []struct {
1114 In interface{}
1115 }{
1116 {In: map[string]int{"one": 1, "two": 2}},
1117 {In: &map[string]int{"one": 1, "two": 2}},
1118 {In: map[int]complex128{5: 1 + 8i, 3: 2}},
1119 }
1120
1121 for idx, tc := range testCases {
1122 t.Run(fmt.Sprintf("test case #%d", idx+1), func(t *testing.T) {
1123 is := assert.New(t)
1124
1125 expected := Values(tc.In)
1126 actual := Chain(tc.In).Values()
1127
1128 is.ElementsMatch(expected, actual)
1129 })
1130 }
1131 }
1132
1133 func TestComplexChaining(t *testing.T) {
1134 is := assert.New(t)
1135
1136 in := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
1137 chain := Chain(in)
1138
1139
1140 fa := Filter(in, func(x int) bool { return x%2 == 0 })
1141 fb := Map(fa, func(x int) int { return x * 2 })
1142 fc := Reverse(fa)
1143
1144
1145 ca := chain.Filter(func(x int) bool { return x%2 == 0 })
1146 cb := ca.Map(func(x int) int { return x * 2 })
1147 cc := ca.Reverse()
1148
1149 is.Equal(fa, ca.Value())
1150 is.Equal(fb, cb.Value())
1151 is.Equal(fc, cc.Value())
1152
1153 is.Equal(Contains(fb, 2), cb.Contains(2))
1154 is.Equal(Contains(fb, 4), cb.Contains(4))
1155 is.Equal(Sum(fb), cb.Sum())
1156 is.Equal(Head(fb), cb.Head())
1157 is.Equal(Head(fc), cc.Head())
1158 }
1159
View as plain text