Skip to content

Commit

Permalink
add stream test (distinct, filter)
Browse files Browse the repository at this point in the history
  • Loading branch information
azihsoyn committed Nov 10, 2016
1 parent 28ade73 commit 16b890d
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 20 deletions.
85 changes: 65 additions & 20 deletions distinct.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,28 @@ func (g *gollection) DistinctBy(f interface{}) *gollection {
return &gollection{err: g.err}
}

sv := reflect.ValueOf(g.slice)
if sv.Kind() != reflect.Slice {
return &gollection{
slice: nil,
err: fmt.Errorf("gollection.DistinctBy called with non-slice value of type %T", g.slice),
}
if g.ch != nil {
return g.distinctByStream(f)
}

funcValue := reflect.ValueOf(f)
funcType := funcValue.Type()
if funcType.Kind() != reflect.Func || funcType.NumIn() != 1 || funcType.NumOut() != 1 {
return g.distinctBy(f)
}

func (g *gollection) distinct() *gollection {
sv := reflect.ValueOf(g.slice)
if sv.Kind() != reflect.Slice {
return &gollection{
slice: nil,
err: fmt.Errorf("gollection.DistinctBy called with invalid func. required func(in <T>) out <T> but supplied %v", g.slice),
err: fmt.Errorf("gollection.Distinct called with non-slice value of type %T", g.slice),
}
}

resultSliceType := reflect.SliceOf(funcType.In(0))
ret := reflect.MakeSlice(resultSliceType, 0, sv.Len())
ret := reflect.MakeSlice(sv.Type(), 0, sv.Len())
m := make(map[interface{}]bool)

for i := 0; i < sv.Len(); i++ {
v := sv.Index(i)
id := funcValue.Call([]reflect.Value{v})[0].Interface()
id := v.Interface()
if _, ok := m[id]; !ok {
ret = reflect.Append(ret, v)
m[id] = true
Expand All @@ -58,21 +56,58 @@ func (g *gollection) DistinctBy(f interface{}) *gollection {
}
}

func (g *gollection) distinct() *gollection {
func (g *gollection) distinctStream() *gollection {
next := &gollection{
ch: make(chan interface{}),
}

m := make(map[interface{}]bool)
go func() {
for {
select {
case v, ok := <-g.ch:
if ok {
if _, ok := m[v]; !ok {
next.ch <- v
m[v] = true
}
} else {
close(next.ch)
return
}
default:
continue
}
}
}()
return next
}

func (g *gollection) distinctBy(f interface{}) *gollection {
sv := reflect.ValueOf(g.slice)
if sv.Kind() != reflect.Slice {
return &gollection{
slice: nil,
err: fmt.Errorf("gollection.Distinct called with non-slice value of type %T", g.slice),
err: fmt.Errorf("gollection.DistinctBy called with non-slice value of type %T", g.slice),
}
}

ret := reflect.MakeSlice(sv.Type(), 0, sv.Len())
funcValue := reflect.ValueOf(f)
funcType := funcValue.Type()
if funcType.Kind() != reflect.Func || funcType.NumIn() != 1 || funcType.NumOut() != 1 {
return &gollection{
slice: nil,
err: fmt.Errorf("gollection.DistinctBy called with invalid func. required func(in <T>) out <T> but supplied %v", g.slice),
}
}

resultSliceType := reflect.SliceOf(funcType.In(0))
ret := reflect.MakeSlice(resultSliceType, 0, sv.Len())
m := make(map[interface{}]bool)

for i := 0; i < sv.Len(); i++ {
v := sv.Index(i)
id := v.Interface()
id := funcValue.Call([]reflect.Value{v})[0].Interface()
if _, ok := m[id]; !ok {
ret = reflect.Append(ret, v)
m[id] = true
Expand All @@ -84,20 +119,30 @@ func (g *gollection) distinct() *gollection {
}
}

func (g *gollection) distinctStream() *gollection {
func (g *gollection) distinctByStream(f interface{}) *gollection {
next := &gollection{
ch: make(chan interface{}),
}

funcValue := reflect.ValueOf(f)
funcType := funcValue.Type()
if funcType.Kind() != reflect.Func || funcType.NumIn() != 1 || funcType.NumOut() != 1 {
return &gollection{
slice: nil,
err: fmt.Errorf("gollection.DistinctBy called with invalid func. required func(in <T>) out <T> but supplied %v", g.slice),
}
}

m := make(map[interface{}]bool)
go func() {
for {
select {
case v, ok := <-g.ch:
if ok {
if _, ok := m[v]; !ok {
id := funcValue.Call([]reflect.Value{reflect.ValueOf(v)})[0].Interface()
if _, ok := m[id]; !ok {
next.ch <- v
m[v] = true
m[id] = true
}
} else {
close(next.ch)
Expand Down
59 changes: 59 additions & 0 deletions distinct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,62 @@ func TestDistinctBy_HavingError(t *testing.T) {
Result()
assert.Error(err)
}

func TestDistinct_Stream(t *testing.T) {
assert := assert.New(t)
arr := []int{1, 2, 3, 1, 2, 3}
expect := []int{1, 2, 3}

res, err := gollection.NewStream(arr).Distinct().Result()
assert.NoError(err)
assert.Equal(expect, res)
}

func TestDistinct_Stream_NotSlice(t *testing.T) {
assert := assert.New(t)
_, err := gollection.NewStream("not slice value").Distinct().Result()
assert.Error(err)
}

func TestDistinct_Stream_HavingError(t *testing.T) {
assert := assert.New(t)
_, err := gollection.NewStream("not slice value").Distinct().Distinct().Result()
assert.Error(err)
}

func TestDistinctBy_Stream(t *testing.T) {
assert := assert.New(t)
arr := []string{"aaa", "bb", "c", "ddd", "ee", "f"}
expect := []string{"aaa", "bb", "c"}

res, err := gollection.NewStream(arr).DistinctBy(func(v string) int {
return len(v)
}).Result()
assert.NoError(err)
assert.Equal(expect, res)
}
func TestDistinctBy_Stream_NotSlice(t *testing.T) {
assert := assert.New(t)
_, err := gollection.NewStream("not slice value").DistinctBy(func(v interface{}) interface{} {
return v
}).Result()
assert.Error(err)
}
func TestDistinctBy_Stream_NotFunc(t *testing.T) {
assert := assert.New(t)
_, err := gollection.NewStream([]int{}).DistinctBy(0).Result()
assert.Error(err)
}

func TestDistinctBy_Stream_HavingError(t *testing.T) {
assert := assert.New(t)
_, err := gollection.NewStream("not slice value").
DistinctBy(func(v interface{}) interface{} {
return v
}).
DistinctBy(func(v interface{}) interface{} {
return v
}).
Result()
assert.Error(err)
}
39 changes: 39 additions & 0 deletions filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,42 @@ func TestFilter_HavingError(t *testing.T) {
Result()
assert.Error(err)
}

func TestFilter_Stream(t *testing.T) {
assert := assert.New(t)
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
expect := []int{6, 7, 8, 9, 10}

res, err := gollection.NewStream(arr).Filter(func(v int) bool {
return v > 5
}).Result()
assert.NoError(err)
assert.Equal(expect, res)
}

func TestFilter_Stream_NotSlice(t *testing.T) {
assert := assert.New(t)
_, err := gollection.NewStream("not slice value").Filter(func(v interface{}) bool {
return true
}).Result()
assert.Error(err)
}

func TestFilter_Stream_NotFunc(t *testing.T) {
assert := assert.New(t)
_, err := gollection.NewStream([]int{0}).Filter(0).Result()
assert.Error(err)
}

func TestFilter_Stream_HavingError(t *testing.T) {
assert := assert.New(t)
_, err := gollection.NewStream("not slice value").
Filter(func(v interface{}) bool {
return true
}).
Filter(func(v interface{}) bool {
return true
}).
Result()
assert.Error(err)
}

0 comments on commit 16b890d

Please sign in to comment.