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 }