github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekaarr/slice_test.go (about)

     1  package ekaarr_test
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  	"unsafe"
     7  
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/qioalice/ekago/v3/ekaarr"
    11  )
    12  
    13  func slicePtr[T comparable](in []T) uintptr {
    14  	return (*reflect.SliceHeader)(unsafe.Pointer(&in)).Data
    15  }
    16  
    17  func TestFilter(t *testing.T) {
    18  
    19  	var in = []int{1, 2, 3, 4, -1, 0, -2, -5}
    20  	var out = []int{1, 2, 3, 4}
    21  	var got = ekaarr.Filter(in, func(n int) bool { return n > 0 })
    22  
    23  	require.Equal(t, out, got)
    24  	require.Equal(t, slicePtr(in), slicePtr(got))
    25  
    26  	in = []int{1, 2, 3, 4}
    27  	out = []int{1, 2, 3, 4}
    28  	got = ekaarr.Filter(in, func(n int) bool { return n > 0 })
    29  
    30  	require.Equal(t, out, got)
    31  	require.Equal(t, slicePtr(in), slicePtr(got))
    32  
    33  	in = []int{-1, -2, -3, 0, -3, -2, -1}
    34  	out = []int{}
    35  	got = ekaarr.Filter(in, func(n int) bool { return n > 0 })
    36  
    37  	require.Equal(t, out, got)
    38  
    39  	in = []int{1, -1, 2, 3, -1, -2, -3, 4, -5, -6, 5, 6, 7}
    40  	out = []int{1, 2, 3, 4, 5, 6, 7}
    41  	got = ekaarr.Filter(in, func(n int) bool { return n > 0 })
    42  
    43  	require.Equal(t, out, got)
    44  }
    45  
    46  func BenchmarkFilter(b *testing.B) {
    47  
    48  	var bg = func(in []int, cb func(int) bool) func(*testing.B) {
    49  		return func(b *testing.B) {
    50  			b.ReportAllocs()
    51  			for i := 0; i < b.N; i++ {
    52  				_ = ekaarr.Filter(in, cb)
    53  			}
    54  		}
    55  	}
    56  
    57  	var f = func(n int) bool { return n > 0 }
    58  
    59  	var in1 = []int{1, 2, 3, 4, -1, 0, -2, -5}
    60  	var in2 = []int{1, 2, 3, 4}
    61  	var in3 = []int{-1, -2, -3, 0, -3, -2, -1}
    62  	var in4 = []int{1, -1, 2, 3, -1, -2, -3, 4, -5, -6, 5, 6, 7}
    63  
    64  	var mul = func(in []int, n int) []int {
    65  		var out = make([]int, 0, len(in)*n)
    66  		for i := 0; i < n; i++ {
    67  			out = append(out, in...)
    68  		}
    69  		return out
    70  	}
    71  
    72  	var sort = func(in []int) []int {
    73  		var pos []int
    74  		var neg []int
    75  		for i, n := 0, len(in); i < n; i++ {
    76  			if in[i] > 0 {
    77  				pos = append(pos, in[i])
    78  			} else {
    79  				neg = append(neg, in[i])
    80  			}
    81  		}
    82  		return append(pos, neg...)
    83  	}
    84  
    85  	b.Run("TrimRight", bg(in1, f))
    86  	b.Run("NoFilter", bg(in2, f))
    87  	b.Run("FilterAll", bg(in3, f))
    88  	b.Run("Common", bg(in4, f))
    89  
    90  	b.Run("TrimRight-x10", bg(sort(mul(in1, 10)), f))
    91  	b.Run("NoFilter-x10", bg(mul(in2, 10), f))
    92  	b.Run("FilterAll-x10", bg(mul(in3, 10), f))
    93  	b.Run("Common-x10", bg(mul(in4, 10), f))
    94  
    95  	b.Run("TrimRight-x100", bg(sort(mul(in1, 100)), f))
    96  	b.Run("NoFilter-x100", bg(mul(in2, 100), f))
    97  	b.Run("FilterAll-x100", bg(mul(in3, 100), f))
    98  	b.Run("Common-x100", bg(mul(in4, 100), f))
    99  }
   100  
   101  func TestContains(t *testing.T) {
   102  
   103  	for _, tc := range []struct {
   104  		In1, In2 []int
   105  		Any, All bool
   106  	}{
   107  		{[]int{1, 2, 3, 4}, []int{1}, true, true},
   108  		{[]int{1, 2, 3, 4}, []int{2, 5}, true, false},
   109  		{[]int{1, 2, 3, 4}, []int{}, false, false},
   110  		{[]int{1, 2, 3, 4}, []int{1, 4}, true, true},
   111  		{[]int{1, 2, 3, 4}, []int{2, 3}, true, true},
   112  		{[]int{1, 2, 3, 4}, []int{0, 1}, true, false},
   113  		{[]int{1, 2, 3, 4}, []int{4, 5}, true, false},
   114  		{[]int{1, 2, 3, 4}, []int{1, 2, 3, 4}, true, true},
   115  		{[]int{}, []int{1, 2}, false, false},
   116  		{[]int{}, []int{}, false, false},
   117  		{[]int{1}, []int{1}, true, true},
   118  		{[]int{1}, []int{1, 2}, true, false},
   119  		{[]int{1, 2}, []int{1}, true, true},
   120  		{[]int{1, 2}, []int{2}, true, true},
   121  		{[]int{1, 2}, []int{3}, false, false},
   122  	} {
   123  		const F1 = "[ANY] In1: %v, In2: %v\n"
   124  		const F2 = "[ALL] In1: %v, In2: %v\n"
   125  
   126  		var r = ekaarr.ContainsAny(tc.In1, tc.In2...)
   127  		require.Equalf(t, tc.Any, r, F1, tc.In1, tc.In2)
   128  
   129  		r = ekaarr.ContainsAll(tc.In1, tc.In2...)
   130  		require.Equalf(t, tc.All, r, F2, tc.In1, tc.In2)
   131  	}
   132  }
   133  
   134  func TestReduce(t *testing.T) {
   135  
   136  	var in = []int{1, 2, 3, 4, 5}
   137  	var sum = 0
   138  	var mul = 1
   139  
   140  	for i, n := 0, len(in); i < n; i++ {
   141  		sum += in[i]
   142  		mul *= in[i]
   143  	}
   144  
   145  	var sumCb = func(acc int, v int, _ int, _ []int) int { return acc + v }
   146  	var mulCb = func(acc int, v int, _ int, _ []int) int { return acc * v }
   147  
   148  	require.Equal(t, sum, ekaarr.Reduce(in, 0, sumCb))
   149  	require.Equal(t, mul, ekaarr.Reduce(in, 1, mulCb))
   150  }
   151  
   152  func TestRemove(t *testing.T) {
   153  
   154  	for _, tc := range []struct {
   155  		In1, In2, Out []int
   156  	}{
   157  		{[]int{1, 2, 3, 4}, []int{1, 2}, []int{3, 4}},
   158  		{[]int{1, 2, 3, 4}, []int{1, 2, 3, 4}, []int{}},
   159  		{[]int{1, 2, 3, 4}, []int{}, []int{1, 2, 3, 4}},
   160  		{[]int{1, 2, 3, 4}, []int{1}, []int{2, 3, 4}},
   161  	} {
   162  		const F = "In1: %v, In2: %v\n"
   163  
   164  		var r = ekaarr.Remove(tc.In1, tc.In2...)
   165  		require.Equalf(t, tc.Out, r, F, tc.In1, tc.In2)
   166  	}
   167  }
   168  
   169  func TestUnique(t *testing.T) {
   170  
   171  	for _, tc := range []struct {
   172  		In, Out []int
   173  	}{
   174  		{[]int{1, 2, 3, 4, 5}, []int{1, 2, 3, 4, 5}},
   175  		{[]int{1, 2}, []int{1, 2}},
   176  		{[]int{1}, []int{1}},
   177  		{[]int{1, 1}, []int{}},
   178  		{[]int{1, 2, 3, 2}, []int{1, 3}},
   179  		{[]int{1, 2, 2, 1}, []int{}},
   180  		{[]int{1, 2, 3, 1}, []int{2, 3}},
   181  		{[]int{1, 1, 1, 1, 4}, []int{4}},
   182  	} {
   183  		const F = "In1: %v\n"
   184  
   185  		var in = append(tc.In[:0:0], tc.In...)
   186  		require.ElementsMatchf(t, tc.Out, ekaarr.Unique(tc.In), F, in)
   187  	}
   188  }
   189  
   190  func TestDistinct(t *testing.T) {
   191  
   192  	for _, tc := range []struct {
   193  		In, Out []int
   194  	}{
   195  		{[]int{1, 2, 3, 4, 5}, []int{1, 2, 3, 4, 5}},
   196  		{[]int{1, 2}, []int{1, 2}},
   197  		{[]int{1}, []int{1}},
   198  		{[]int{1, 1}, []int{1}},
   199  		{[]int{1, 2, 3, 2}, []int{1, 2, 3}},
   200  		{[]int{1, 2, 2, 1}, []int{1, 2}},
   201  		{[]int{1, 2, 3, 1}, []int{1, 2, 3}},
   202  		{[]int{1, 1, 1, 1, 4}, []int{1, 4}},
   203  	} {
   204  		const F = "In1: %v\n"
   205  
   206  		require.ElementsMatchf(t, tc.Out, ekaarr.Distinct(tc.In), F, tc.In)
   207  	}
   208  }