github.com/m4gshm/gollections@v0.0.10/loop/test/api_test.go (about)

     1  package test
     2  
     3  import (
     4  	"errors"
     5  	"strconv"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  
    11  	breakLoop "github.com/m4gshm/gollections/break/loop"
    12  	"github.com/m4gshm/gollections/c"
    13  	"github.com/m4gshm/gollections/convert/as"
    14  	kvloop "github.com/m4gshm/gollections/kv/loop"
    15  	kvloopgroup "github.com/m4gshm/gollections/kv/loop/group"
    16  	"github.com/m4gshm/gollections/loop"
    17  	"github.com/m4gshm/gollections/loop/conv"
    18  	"github.com/m4gshm/gollections/loop/convert"
    19  	"github.com/m4gshm/gollections/loop/filter"
    20  	"github.com/m4gshm/gollections/loop/first"
    21  	"github.com/m4gshm/gollections/loop/flat"
    22  	"github.com/m4gshm/gollections/loop/range_"
    23  	"github.com/m4gshm/gollections/op"
    24  	"github.com/m4gshm/gollections/predicate/eq"
    25  	"github.com/m4gshm/gollections/predicate/more"
    26  	"github.com/m4gshm/gollections/slice"
    27  )
    28  
    29  func Test_ReduceSum(t *testing.T) {
    30  	s := loop.Of(1, 3, 5, 7, 9, 11)
    31  	r := loop.Reduce(s, op.Sum[int])
    32  	assert.Equal(t, 1+3+5+7+9+11, r)
    33  }
    34  
    35  func Test_EmptyLoop(t *testing.T) {
    36  	s := loop.Of[int]()
    37  	r := loop.Reduce(s, op.Sum[int])
    38  	assert.Equal(t, 0, r)
    39  }
    40  
    41  func Test_ConvertAndReduce(t *testing.T) {
    42  	s := loop.Of(1, 3, 5, 7, 9, 11)
    43  	r := convert.AndReduce(s, func(i int) int { return i * i }, op.Sum[int])
    44  	assert.Equal(t, 1+3*3+5*5+7*7+9*9+11*11, r)
    45  }
    46  
    47  func Test_ConvAndReduce(t *testing.T) {
    48  	s := loop.Of("1", "3", "5", "7", "9", "11")
    49  	r, err := conv.AndReduce(s, strconv.Atoi, op.Sum[int])
    50  	assert.NoError(t, err)
    51  	assert.Equal(t, 1+3+5+7+9+11, r)
    52  }
    53  
    54  func Test_Sum(t *testing.T) {
    55  	s := loop.Of(1, 3, 5, 7, 9, 11)
    56  	r := loop.Sum(s)
    57  	assert.Equal(t, 1+3+5+7+9+11, r)
    58  }
    59  
    60  func Test_First(t *testing.T) {
    61  	s := loop.Of(1, 3, 5, 7, 9, 11)
    62  	r, ok := first.Of(s, func(i int) bool { return i > 5 })
    63  	assert.True(t, ok)
    64  	assert.Equal(t, 7, r)
    65  
    66  	_, nook := loop.First(s, func(i int) bool { return i > 12 })
    67  	assert.False(t, nook)
    68  }
    69  
    70  func Test_FirstConverted(t *testing.T) {
    71  	s := loop.Of(1, 3, 5, 7, 9, 11)
    72  	r, ok := first.Converted(s, func(i int) bool { return i > 5 }, strconv.Itoa)
    73  	assert.True(t, ok)
    74  	assert.Equal(t, "7", r)
    75  }
    76  
    77  func Test_NotNil(t *testing.T) {
    78  	type entity struct{ val string }
    79  	var (
    80  		source   = loop.Of([]*entity{{"first"}, nil, {"third"}, nil, {"fifth"}}...)
    81  		result   = loop.NotNil(source)
    82  		expected = []*entity{{"first"}, {"third"}, {"fifth"}}
    83  	)
    84  	assert.Equal(t, expected, loop.Slice(result.Next))
    85  }
    86  
    87  func Test_ConvertPointersToValues(t *testing.T) {
    88  	type entity struct{ val string }
    89  	var (
    90  		source   = loop.Of([]*entity{{"first"}, nil, {"third"}, nil, {"fifth"}}...)
    91  		result   = loop.PtrVal(source)
    92  		expected = []entity{{"first"}, {}, {"third"}, {}, {"fifth"}}
    93  	)
    94  	assert.Equal(t, expected, loop.Slice(result.Next))
    95  }
    96  
    97  func Test_ConvertNotnilPointersToValues(t *testing.T) {
    98  	type entity struct{ val string }
    99  	var (
   100  		source   = loop.Of([]*entity{{"first"}, nil, {"third"}, nil, {"fifth"}}...)
   101  		result   = loop.NoNilPtrVal(source)
   102  		expected = []entity{{"first"}, {"third"}, {"fifth"}}
   103  	)
   104  	assert.Equal(t, expected, loop.Slice(result.Next))
   105  }
   106  
   107  func Test_Convert(t *testing.T) {
   108  	s := loop.Of(1, 3, 5, 7, 9, 11)
   109  	r := loop.Convert(s, strconv.Itoa)
   110  	assert.Equal(t, []string{"1", "3", "5", "7", "9", "11"}, loop.Slice(r.Next))
   111  }
   112  
   113  func Test_IterWitErr(t *testing.T) {
   114  	s := loop.Of("1", "3", "5", "7eee", "9", "11")
   115  	r := []int{}
   116  	var outErr error
   117  	for it, i, ok, err := loop.Conv(s, strconv.Atoi).Start(); ok || err != nil; i, ok, err = it.Next() {
   118  		if err != nil {
   119  			outErr = err
   120  			break
   121  		}
   122  		r = append(r, i)
   123  	}
   124  
   125  	assert.Error(t, outErr)
   126  	assert.Equal(t, []int{1, 3, 5}, r)
   127  
   128  	s = loop.Of("1", "3", "5", "7eee", "9", "11")
   129  	r = []int{}
   130  	//ignore err
   131  	for it, i, ok, err := loop.Conv(s, strconv.Atoi).Start(); ok || err != nil; i, ok, err = it.Next() {
   132  		if err == nil {
   133  			r = append(r, i)
   134  		}
   135  	}
   136  	assert.Equal(t, []int{1, 3, 5, 9, 11}, r)
   137  }
   138  
   139  func Test_IterStart(t *testing.T) {
   140  	l := loop.Convert(loop.Of(1, 3, 5, 7, 9, 11), strconv.Itoa)
   141  	r := []string{}
   142  
   143  	for it, i, ok := l.Start(); ok; i, ok = it.Next() {
   144  		r = append(r, i)
   145  	}
   146  	assert.Equal(t, []string{"1", "3", "5", "7", "9", "11"}, r)
   147  }
   148  
   149  func Test_ConvertNotNil(t *testing.T) {
   150  	type entity struct{ val string }
   151  	var (
   152  		source   = loop.Of([]*entity{{"first"}, nil, {"third"}, nil, {"fifth"}}...)
   153  		result   = convert.NotNil(source, func(e *entity) string { return e.val })
   154  		expected = []string{"first", "third", "fifth"}
   155  	)
   156  	assert.Equal(t, expected, loop.Slice(result.Next))
   157  }
   158  
   159  func Test_ConvertToNotNil(t *testing.T) {
   160  	type entity struct{ val *string }
   161  	var (
   162  		first    = "first"
   163  		third    = "third"
   164  		fifth    = "fifth"
   165  		source   = loop.Of([]entity{{&first}, {}, {&third}, {}, {&fifth}}...)
   166  		result   = convert.ToNotNil(source, func(e entity) *string { return e.val })
   167  		expected = []*string{&first, &third, &fifth}
   168  	)
   169  	assert.Equal(t, expected, loop.Slice(result.Next))
   170  }
   171  
   172  func Test_ConvertNilSafe(t *testing.T) {
   173  	type entity struct{ val *string }
   174  	var (
   175  		first    = "first"
   176  		third    = "third"
   177  		fifth    = "fifth"
   178  		source   = loop.Of([]*entity{{&first}, {}, {&third}, nil, {&fifth}}...)
   179  		result   = convert.NilSafe(source, func(e *entity) *string { return e.val })
   180  		expected = []*string{&first, &third, &fifth}
   181  	)
   182  	assert.Equal(t, expected, loop.Slice(result.Next))
   183  }
   184  
   185  var even = func(v int) bool { return v%2 == 0 }
   186  
   187  func Test_ConvertFiltered(t *testing.T) {
   188  	s := loop.Of(1, 3, 4, 5, 7, 8, 9, 11)
   189  	r := loop.FilterAndConvert(s, even, strconv.Itoa)
   190  	assert.Equal(t, []string{"4", "8"}, loop.Slice(r.Next))
   191  }
   192  
   193  func Test_ConvertFilteredInplace(t *testing.T) {
   194  	s := loop.Of(1, 3, 4, 5, 7, 8, 9, 11)
   195  	r := loop.ConvertCheck(s, func(i int) (string, bool) { return strconv.Itoa(i), even(i) })
   196  	assert.Equal(t, []string{"4", "8"}, loop.Slice(r.Next))
   197  }
   198  
   199  func Test_Flat(t *testing.T) {
   200  	md := loop.Of([][]int{{1, 2, 3}, {4}, {5, 6}}...)
   201  	f := loop.Flat(md, func(i []int) []int { return i })
   202  	e := []int{1, 2, 3, 4, 5, 6}
   203  	assert.Equal(t, e, loop.Slice(f.Next))
   204  }
   205  
   206  func Test_FlatAndConvert(t *testing.T) {
   207  	md := loop.Of([][]int{{1, 2, 3}, {4}, {5, 6}}...)
   208  	f := flat.AndConvert(md, func(i []int) []int { return i }, strconv.Itoa)
   209  	e := []string{"1", "2", "3", "4", "5", "6"}
   210  	assert.Equal(t, e, loop.Slice(f.Next))
   211  }
   212  
   213  func Test_FlatFilter(t *testing.T) {
   214  	md := loop.Of([][]int{{1, 2, 3}, {4}, {5, 6}}...)
   215  	f := loop.FilterAndFlat(md, func(from []int) bool { return len(from) > 1 }, func(i []int) []int { return i })
   216  	e := []int{1, 2, 3, 5, 6}
   217  	assert.Equal(t, e, loop.Slice(f.Next))
   218  }
   219  
   220  func Test_FlattElemFilter(t *testing.T) {
   221  	md := loop.Of([][]int{{1, 2, 3}, {4}, {5, 6}}...)
   222  	f := loop.FlattAndFilter(md, func(i []int) []int { return i }, even)
   223  	e := []int{2, 4, 6}
   224  	assert.Equal(t, e, loop.Slice(f.Next))
   225  }
   226  
   227  func Test_FilterAndFlattFilt(t *testing.T) {
   228  	md := loop.Of([][]int{{1, 2, 3}, {4}, {5, 6}}...)
   229  	f := loop.FilterFlatFilter(md, func(from []int) bool { return len(from) > 1 }, func(i []int) []int { return i }, even)
   230  	e := []int{2, 6}
   231  	assert.Equal(t, e, loop.Slice(f.Next))
   232  }
   233  
   234  func Test_Filter(t *testing.T) {
   235  	s := loop.Of(1, 3, 4, 5, 7, 8, 9, 11)
   236  	r := loop.Filter(s, even)
   237  	assert.Equal(t, slice.Of(4, 8), loop.Slice(r.Next))
   238  }
   239  
   240  func Test_FilterConvertFilter(t *testing.T) {
   241  	s := loop.Of(1, 3, 4, 5, 7, 8, 9, 11)
   242  	r := filter.ConvertFilter(s, even, func(i int) int { return i * 2 }, even)
   243  	assert.Equal(t, slice.Of(8, 16), loop.Slice(r.Next))
   244  }
   245  
   246  func Test_Filt(t *testing.T) {
   247  	s := loop.Of(1, 3, 4, 5, 7, 8, 9, 11)
   248  	l := loop.Filt(s, func(i int) (bool, error) { return even(i), op.IfElse(i > 7, errors.New("abort"), nil) })
   249  	r, err := breakLoop.Slice(l.Next)
   250  	assert.Error(t, err)
   251  	assert.Equal(t, slice.Of(4, 8), r)
   252  }
   253  
   254  func Test_Filt2(t *testing.T) {
   255  	s := loop.Of(1, 3, 4, 5, 7, 8, 9, 11)
   256  	l := loop.Filt(s, func(i int) (bool, error) {
   257  		ok := i <= 7
   258  		return ok && even(i), op.IfElse(ok, nil, errors.New("abort"))
   259  	})
   260  	r, err := breakLoop.Slice(l.Next)
   261  	assert.Error(t, err)
   262  	assert.Equal(t, slice.Of(4), r)
   263  }
   264  
   265  func Test_FiltAndConv(t *testing.T) {
   266  	s := loop.Of(1, 3, 4, 5, 7, 8, 9, 11)
   267  	r := loop.FiltAndConv(s, func(v int) (bool, error) { return v%2 == 0, nil }, func(i int) (int, error) { return i * 2, nil })
   268  	o, _ := breakLoop.Slice(r.Next)
   269  	assert.Equal(t, slice.Of(8, 16), o)
   270  }
   271  
   272  func Test_Filtering(t *testing.T) {
   273  	r := loop.Filter(loop.Of(1, 2, 3, 4, 5, 6), func(i int) bool { return i%2 == 0 })
   274  	assert.Equal(t, []int{2, 4, 6}, loop.Slice(r.Next))
   275  }
   276  
   277  type rows[T any] struct {
   278  	row    []T
   279  	cursor int
   280  }
   281  
   282  func (r *rows[T]) hasNext() bool    { return r.cursor < len(r.row) }
   283  func (r *rows[T]) next() (T, error) { e := r.row[r.cursor]; r.cursor++; return e, nil }
   284  
   285  func Test_OfLoop(t *testing.T) {
   286  	stream := loop.Of(1, 2, 3)
   287  	result := loop.Slice(stream)
   288  
   289  	assert.Equal(t, slice.Of(1, 2, 3), result)
   290  }
   291  
   292  func Test_MatchAny(t *testing.T) {
   293  	elements := loop.Of(1, 2, 3, 4)
   294  
   295  	ok := loop.HasAny(elements, eq.To(4))
   296  	assert.True(t, ok)
   297  
   298  	noOk := loop.HasAny(elements, more.Than(5))
   299  	assert.False(t, noOk)
   300  }
   301  
   302  type Role struct {
   303  	name string
   304  }
   305  
   306  type User struct {
   307  	name  string
   308  	age   int
   309  	roles []Role
   310  }
   311  
   312  func (u User) Name() string  { return u.name }
   313  func (u User) Age() int      { return u.age }
   314  func (u User) Roles() []Role { return u.roles }
   315  
   316  var users = []User{
   317  	{name: "Bob", age: 26, roles: []Role{{"Admin"}, {"manager"}}},
   318  	{name: "Alice", age: 35, roles: []Role{{"Manager"}}},
   319  	{name: "Tom", age: 18}, {},
   320  }
   321  
   322  func Test_KeyValuer(t *testing.T) {
   323  	m := kvloop.Group(loop.KeyValue(loop.Of(users...), User.Name, User.Age).Next)
   324  
   325  	assert.Equal(t, m["Alice"], slice.Of(35))
   326  	assert.Equal(t, m["Bob"], slice.Of(26))
   327  	assert.Equal(t, m["Tom"], slice.Of(18))
   328  
   329  	g := loop.Group(loop.Of(users...), User.Name, User.Age)
   330  	assert.Equal(t, m, g)
   331  }
   332  
   333  func Test_Keyer(t *testing.T) {
   334  	m := kvloop.Group(loop.ExtraKey(loop.Of(users...), User.Name).Next)
   335  
   336  	assert.Equal(t, m["Alice"], slice.Of(users[1]))
   337  	assert.Equal(t, m["Bob"], slice.Of(users[0]))
   338  	assert.Equal(t, m["Tom"], slice.Of(users[2]))
   339  
   340  	g := loop.Group(loop.Of(users...), User.Name, as.Is[User])
   341  	assert.Equal(t, m, g)
   342  }
   343  
   344  func Test_Valuer(t *testing.T) {
   345  	bob, bobRoles, _ := loop.ExtraValue(loop.Of(users...), User.Roles).Next()
   346  
   347  	assert.Equal(t, bob, users[0])
   348  	assert.Equal(t, bobRoles, users[0].roles)
   349  }
   350  
   351  func Test_MultiValuer(t *testing.T) {
   352  	l := loop.ExtraVals(loop.Of(users...), User.Roles)
   353  	bob, bobRole, _ := l.Next()
   354  	bob2, bobRole2, _ := l.Next()
   355  
   356  	assert.Equal(t, bob, users[0])
   357  	assert.Equal(t, bob2, users[0])
   358  	assert.Equal(t, bobRole, users[0].roles[0])
   359  	assert.Equal(t, bobRole2, users[0].roles[1])
   360  }
   361  
   362  func Test_MultipleKeyValuer(t *testing.T) {
   363  	m := kvloop.Group(loop.KeysValues(loop.Of(users...),
   364  		func(u User) []string {
   365  			return slice.Convert(u.roles, func(r Role) string { return strings.ToLower(r.name) })
   366  		},
   367  		func(u User) []string { return []string{u.name, strings.ToLower(u.name)} },
   368  	).Next)
   369  
   370  	assert.Equal(t, m["admin"], slice.Of("Bob", "bob"))
   371  	assert.Equal(t, m["manager"], slice.Of("Bob", "bob", "Alice", "alice"))
   372  	assert.Equal(t, m[""], slice.Of("Tom", "tom", "", ""))
   373  }
   374  
   375  func Test_Range(t *testing.T) {
   376  	assert.Equal(t, slice.Of(-1, 0, 1, 2, 3), loop.Slice(range_.Of(-1, 4)))
   377  	assert.Equal(t, slice.Of(3, 2, 1, 0, -1), loop.Slice(range_.Of(3, -2)))
   378  	assert.Nil(t, loop.Slice(range_.Of(1, 1)))
   379  }
   380  
   381  func Test_RangeClosed(t *testing.T) {
   382  	assert.Equal(t, slice.Of(-1, 0, 1, 2, 3), loop.Slice(range_.Closed(-1, 3)))
   383  	assert.Equal(t, slice.Of(3, 2, 1, 0, -1), loop.Slice(range_.Closed(3, -1)))
   384  	assert.Equal(t, slice.Of(1), loop.Slice(range_.Closed(1, 1)))
   385  }
   386  
   387  func Test_OfIndexed(t *testing.T) {
   388  	indexed := slice.Of("0", "1", "2", "3", "4")
   389  	result := loop.Slice(loop.OfIndexed(len(indexed), func(i int) string { return indexed[i] }))
   390  	assert.Equal(t, indexed, result)
   391  }
   392  
   393  func Test_ConvertIndexed(t *testing.T) {
   394  	indexed := slice.Of(10, 11, 12, 13, 14)
   395  	result := loop.Slice(convert.FromIndexed(len(indexed), func(i int) int { return indexed[i] }, strconv.Itoa).Next)
   396  	assert.Equal(t, slice.Of("10", "11", "12", "13", "14"), result)
   397  }
   398  
   399  func Test_ConvIndexed(t *testing.T) {
   400  	indexed := slice.Of("10", "11", "12", "13", "14")
   401  	result, err := breakLoop.Slice(conv.FromIndexed(len(indexed), func(i int) string { return indexed[i] }, strconv.Atoi).Next)
   402  	assert.NoError(t, err)
   403  	assert.Equal(t, slice.Of(10, 11, 12, 13, 14), result)
   404  }
   405  
   406  func Test_Containt(t *testing.T) {
   407  	assert.True(t, loop.Contains(loop.Of(1, 2, 3), 3))
   408  	assert.False(t, loop.Contains(loop.Of(1, 2, 3), 0))
   409  }
   410  
   411  func Test_New(t *testing.T) {
   412  	source := []string{"one", "two", "three"}
   413  	i := 0
   414  	l := loop.New(source, func(s []string) bool { return i < len(s) }, func(s []string) string { o := s[i]; i++; return o })
   415  
   416  	assert.Equal(t, source, loop.Slice(l))
   417  }
   418  
   419  func Test_For(t *testing.T) {
   420  	var out []int
   421  	err := loop.For(loop.Of(1, 2, 3, 4), func(i int) error {
   422  		if i == 3 {
   423  			return c.ErrBreak
   424  		}
   425  		out = append(out, i)
   426  		return nil
   427  	})
   428  	assert.NoError(t, err)
   429  	assert.Equal(t, slice.Of(1, 2), out)
   430  }
   431  
   432  func Test_ForEachFiltered(t *testing.T) {
   433  	var out []int
   434  	loop.ForEachFiltered(loop.Of(1, 2, 3, 4), even, func(i int) { out = append(out, i) })
   435  	assert.Equal(t, slice.Of(2, 4), out)
   436  }
   437  
   438  func Test_FlatValues(t *testing.T) {
   439  	g := kvloopgroup.Of(loop.KeyValues(loop.Of(users...), func(u User) string { return u.name }, func(u User) []int { return slice.Of(u.age) }).Next)
   440  
   441  	assert.Equal(t, g["Bob"], slice.Of(26))
   442  }
   443  
   444  func Test_FlatKeys(t *testing.T) {
   445  	g := kvloopgroup.Of(loop.KeysValue(loop.Of(users...), func(u User) []string { return slice.Of(u.name) }, func(u User) int { return u.age }).Next)
   446  	assert.Equal(t, g["Alice"], slice.Of(35))
   447  }