1 package funk
2
3 import (
4 "fmt"
5 "reflect"
6 "testing"
7
8 "github.com/stretchr/testify/assert"
9 )
10
11 func TestLazyChunk(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 := LazyChain(tc.In).Chunk(tc.Size).Value()
27
28 is.Equal(expected, actual)
29 })
30 }
31 }
32
33 func TestLazyCompact(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 := LazyChain(tc.In).Compact().Value()
74
75 is.Equal(expected, actual)
76 })
77 }
78 }
79
80 func TestLazyDrop(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 := LazyChain(tc.In).Drop(tc.N).Value()
97
98 is.Equal(expected, actual)
99 })
100 }
101 }
102
103 func TestLazyFilter(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 := LazyChain(tc.In).Filter(tc.Predicate).Value()
120
121 is.Equal(expected, actual)
122 })
123 }
124 }
125 func TestLazyFilter_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 LazyChain := LazyChain(in)
134 is.Equal([]*foo{&foo{"foo"}, &foo{"bar"}}, LazyChain.Value())
135
136 filtered := LazyChain.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"}}, LazyChain.Value())
144 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, in)
145 }
146
147 func TestLazyFlatten(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 := LazyChain(tc.In).Flatten().Value()
165
166 is.Equal(expected, actual)
167 })
168 }
169 }
170
171 func TestLazyFlattenDeep(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 := LazyChain(tc.In).FlattenDeep().Value()
189
190 is.Equal(expected, actual)
191 })
192 }
193 }
194
195 func TestLazyInitial(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 := LazyChain(tc.In).Initial().Value()
216
217 is.Equal(expected, actual)
218 })
219 }
220 }
221
222 func TestLazyIntersect(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 := LazyChain(tc.In).Intersect(tc.Sec).Value()
243
244 is.Equal(expected, actual)
245 })
246 }
247 }
248
249 func TestLazyMap(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 := LazyChain(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 TestLazyFlatMap(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 := Map(tc.In, tc.FlatMapFnc)
308 actual := LazyChain(tc.In).Map(tc.FlatMapFnc).Value()
309
310 is.ElementsMatch(expected, actual)
311 })
312 }
313 }
314
315 func TestLazyMap_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 LazyChain := LazyChain(in)
324 is.Equal([]*foo{&foo{"foo"}, &foo{"bar"}}, LazyChain.Value())
325
326 mapped := LazyChain.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"}}, LazyChain.Value())
334 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, in)
335 }
336
337 func TestLazyReverse(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 := LazyChain(tc.In).Reverse().Value()
355
356 is.Equal(expected, actual)
357 })
358 }
359 }
360
361 func TestLazyShuffle(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 := LazyChain(tc.In).Shuffle().Value()
376
377 is.NotEqual(expected, actual)
378 is.ElementsMatch(expected, actual)
379 })
380 }
381 }
382
383 func TestLazyTail(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 := LazyChain(tc.In).Tail().Value()
404
405 is.Equal(expected, actual)
406 })
407 }
408 }
409
410 func TestLazyUniq(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 := LazyChain(tc.In).Uniq().Value()
425
426 is.Equal(expected, actual)
427 })
428 }
429 }
430
431 func TestLazyAll(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 := LazyChain(tc.In).All()
452
453 is.Equal(expected, actual)
454 })
455 }
456 }
457
458 func TestLazyAny(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 := LazyChain(tc.In).Any()
479
480 is.Equal(expected, actual)
481 })
482 }
483 }
484
485 func TestLazyContains(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 := LazyChain(tc.In).Contains(tc.Contains)
542
543 is.Equal(expected, actual)
544 })
545 }
546 }
547
548 func TestLazyEvery(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 := LazyChain(tc.In).Every(tc.Contains...)
593
594 is.Equal(expected, actual)
595 })
596 }
597 }
598
599 func TestLazyFind(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 := LazyChain(tc.In).Find(tc.Predicate)
616
617 is.Equal(expected, actual)
618 })
619 }
620 }
621
622 func TestLazyFind_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 LazyChain := LazyChain(in)
631 is.Equal([]*foo{&foo{"foo"}, &foo{"bar"}}, LazyChain.Value())
632
633 result := LazyChain.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"}}, LazyChain.Value())
641 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, in)
642 }
643
644 func TestLazyForEach(t *testing.T) {
645 var expectedAcc, actualAcc []interface{}
646
647 testCases := []struct {
648 In interface{}
649 FunkIterator interface{}
650 LazyChainIterator 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 LazyChainIterator: 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 LazyChainIterator: 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 LazyChain(tc.In).ForEach(tc.LazyChainIterator)
680
681 is.ElementsMatch(expectedAcc, actualAcc)
682 })
683 }
684 }
685
686 func TestLazyForEach_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 LazyChain := LazyChain(in)
696 is.Equal([]*foo{&foo{"foo"}, &foo{"bar"}}, LazyChain.Value())
697
698 LazyChain.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"}}, LazyChain.Value())
706 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, in)
707 }
708
709 func TestLazyForEachRight(t *testing.T) {
710 var expectedAcc, actualAcc []interface{}
711
712 testCases := []struct {
713 In interface{}
714 FunkIterator interface{}
715 LazyChainIterator 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 LazyChainIterator: 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 LazyChainIterator: 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 LazyChain(tc.In).ForEachRight(tc.LazyChainIterator)
745
746 is.ElementsMatch(expectedAcc, actualAcc)
747 })
748 }
749 }
750
751 func TestLazyForEachRight_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 LazyChain := LazyChain(in)
761 is.Equal([]*foo{&foo{"foo"}, &foo{"bar"}}, LazyChain.Value())
762
763 LazyChain.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"}}, LazyChain.Value())
771 is.NotEqual([]*foo{&foo{"foo"}, &foo{"bar"}}, in)
772 }
773
774 func TestLazyHead(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 := LazyChain(tc.In).Head()
789
790 is.Equal(expected, actual)
791 })
792 }
793 }
794
795 func TestLazyKeys(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 := LazyChain(tc.In).Keys()
810
811 is.ElementsMatch(expected, actual)
812 })
813 }
814 }
815
816 func TestLazyIndexOf(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 := LazyChain(tc.In).IndexOf(tc.Item)
847
848 is.Equal(expected, actual)
849 })
850 }
851 }
852
853 func TestLazyIsEmpty(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 := LazyChain(tc.In).IsEmpty()
873
874 is.Equal(expected, actual)
875 })
876 }
877 }
878
879 func TestLazyLast(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 := LazyChain(tc.In).Last()
894
895 is.Equal(expected, actual)
896 })
897 }
898 }
899
900 func TestLazyLastIndexOf(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 := LazyChain(tc.In).LastIndexOf(tc.Item)
931
932 is.Equal(expected, actual)
933 })
934 }
935 }
936
937 func TestLazyNotEmpty(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 := LazyChain(tc.In).NotEmpty()
957
958 is.Equal(expected, actual)
959 })
960 }
961 }
962
963 func TestLazyProduct(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 := LazyChain(tc.In).Product()
978
979 is.Equal(expected, actual)
980 })
981 }
982 }
983
984 func TestLazyReduce(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 := LazyChain(tc.In).Reduce(tc.ReduceFunc, tc.Acc)
1028
1029 is.Equal(expected, actual)
1030 })
1031 }
1032 }
1033
1034 func TestLazySum(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 := LazyChain(tc.In).Sum()
1049
1050 is.Equal(expected, actual)
1051 })
1052 }
1053 }
1054
1055 func TestLazyType(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 := LazyChain(tc.In).Type()
1082
1083 is.Equal(reflect.TypeOf(tc.In), actual)
1084 })
1085 }
1086 }
1087
1088 func TestLazyValue(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 := LazyChain(tc.In).Value()
1106
1107 is.Equal(tc.In, actual)
1108 })
1109 }
1110 }
1111
1112 func TestLazyValues(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 := LazyChain(tc.In).Values()
1127
1128 is.ElementsMatch(expected, actual)
1129 })
1130 }
1131 }
1132
1133 func TestComplexLazyChaining(t *testing.T) {
1134 is := assert.New(t)
1135
1136 in := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
1137 lazy := LazyChain(in)
1138 lazyWith := LazyChainWith(func() interface{} { return in })
1139
1140
1141 fa := Filter(in, func(x int) bool { return x%2 == 0 })
1142 fb := Map(fa, func(x int) int { return x * 2 })
1143 fc := Reverse(fa)
1144
1145
1146 la := lazy.Filter(func(x int) bool { return x%2 == 0 })
1147 lb := la.Map(func(x int) int { return x * 2 })
1148 lc := la.Reverse()
1149
1150
1151 lwa := lazyWith.Filter(func(x int) bool { return x%2 == 0 })
1152 lwb := lwa.Map(func(x int) int { return x * 2 })
1153 lwc := lwa.Reverse()
1154
1155 is.Equal(fa, la.Value())
1156 is.Equal(fb, lb.Value())
1157 is.Equal(fc, lc.Value())
1158 is.Equal(fa, lwa.Value())
1159 is.Equal(fb, lwb.Value())
1160 is.Equal(fc, lwc.Value())
1161
1162 is.Equal(Contains(fb, 2), lb.Contains(2))
1163 is.Equal(Contains(fb, 4), lb.Contains(4))
1164 is.Equal(Sum(fb), lb.Sum())
1165 is.Equal(Head(fb), lb.Head())
1166 is.Equal(Head(fc), lc.Head())
1167 is.Equal(Contains(fb, 2), lwb.Contains(2))
1168 is.Equal(Contains(fb, 4), lwb.Contains(4))
1169 is.Equal(Sum(fb), lwb.Sum())
1170 is.Equal(Head(fb), lwb.Head())
1171 is.Equal(Head(fc), lwc.Head())
1172 }
1173
View as plain text