@ -17,6 +17,7 @@ import (
)
)
func TestBuffer ( t * testing . T ) {
func TestBuffer ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
const N = 5
const N = 5
var count int32
var count int32
var wait sync . WaitGroup
var wait sync . WaitGroup
@ -39,9 +40,11 @@ func TestBuffer(t *testing.T) {
// why N+1, because take one more to wait for sending into the channel
// why N+1, because take one more to wait for sending into the channel
assert . Equal ( t , int32 ( N + 1 ) , atomic . LoadInt32 ( & count ) )
assert . Equal ( t , int32 ( N + 1 ) , atomic . LoadInt32 ( & count ) )
} )
} )
} )
}
}
func TestBufferNegative ( t * testing . T ) {
func TestBufferNegative ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var result int
var result int
Just ( 1 , 2 , 3 , 4 ) . Buffer ( - 1 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
Just ( 1 , 2 , 3 , 4 ) . Buffer ( - 1 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
for item := range pipe {
for item := range pipe {
@ -50,9 +53,11 @@ func TestBufferNegative(t *testing.T) {
return result , nil
return result , nil
} )
} )
assert . Equal ( t , 10 , result )
assert . Equal ( t , 10 , result )
} )
}
}
func TestCount ( t * testing . T ) {
func TestCount ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
tests := [ ] struct {
tests := [ ] struct {
name string
name string
elements [ ] interface { }
elements [ ] interface { }
@ -80,18 +85,22 @@ func TestCount(t *testing.T) {
assert . Equal ( t , len ( test . elements ) , val )
assert . Equal ( t , len ( test . elements ) , val )
} )
} )
}
}
} )
}
}
func TestDone ( t * testing . T ) {
func TestDone ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var count int32
var count int32
Just ( 1 , 2 , 3 ) . Walk ( func ( item interface { } , pipe chan <- interface { } ) {
Just ( 1 , 2 , 3 ) . Walk ( func ( item interface { } , pipe chan <- interface { } ) {
time . Sleep ( time . Millisecond * 100 )
time . Sleep ( time . Millisecond * 100 )
atomic . AddInt32 ( & count , int32 ( item . ( int ) ) )
atomic . AddInt32 ( & count , int32 ( item . ( int ) ) )
} ) . Done ( )
} ) . Done ( )
assert . Equal ( t , int32 ( 6 ) , count )
assert . Equal ( t , int32 ( 6 ) , count )
} )
}
}
func TestJust ( t * testing . T ) {
func TestJust ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var result int
var result int
Just ( 1 , 2 , 3 , 4 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
Just ( 1 , 2 , 3 , 4 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
for item := range pipe {
for item := range pipe {
@ -100,9 +109,11 @@ func TestJust(t *testing.T) {
return result , nil
return result , nil
} )
} )
assert . Equal ( t , 10 , result )
assert . Equal ( t , 10 , result )
} )
}
}
func TestDistinct ( t * testing . T ) {
func TestDistinct ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var result int
var result int
Just ( 4 , 1 , 3 , 2 , 3 , 4 ) . Distinct ( func ( item interface { } ) interface { } {
Just ( 4 , 1 , 3 , 2 , 3 , 4 ) . Distinct ( func ( item interface { } ) interface { } {
return item
return item
@ -113,9 +124,11 @@ func TestDistinct(t *testing.T) {
return result , nil
return result , nil
} )
} )
assert . Equal ( t , 10 , result )
assert . Equal ( t , 10 , result )
} )
}
}
func TestFilter ( t * testing . T ) {
func TestFilter ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var result int
var result int
Just ( 1 , 2 , 3 , 4 ) . Filter ( func ( item interface { } ) bool {
Just ( 1 , 2 , 3 , 4 ) . Filter ( func ( item interface { } ) bool {
return item . ( int ) % 2 == 0
return item . ( int ) % 2 == 0
@ -126,9 +139,19 @@ func TestFilter(t *testing.T) {
return result , nil
return result , nil
} )
} )
assert . Equal ( t , 6 , result )
assert . Equal ( t , 6 , result )
} )
}
func TestFirst ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
assert . Nil ( t , Just ( ) . First ( ) )
assert . Equal ( t , "foo" , Just ( "foo" ) . First ( ) )
assert . Equal ( t , "foo" , Just ( "foo" , "bar" ) . First ( ) )
} )
}
}
func TestForAll ( t * testing . T ) {
func TestForAll ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var result int
var result int
Just ( 1 , 2 , 3 , 4 ) . Filter ( func ( item interface { } ) bool {
Just ( 1 , 2 , 3 , 4 ) . Filter ( func ( item interface { } ) bool {
return item . ( int ) % 2 == 0
return item . ( int ) % 2 == 0
@ -138,9 +161,11 @@ func TestForAll(t *testing.T) {
}
}
} )
} )
assert . Equal ( t , 6 , result )
assert . Equal ( t , 6 , result )
} )
}
}
func TestGroup ( t * testing . T ) {
func TestGroup ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var groups [ ] [ ] int
var groups [ ] [ ] int
Just ( 10 , 11 , 20 , 21 ) . Group ( func ( item interface { } ) interface { } {
Just ( 10 , 11 , 20 , 21 ) . Group ( func ( item interface { } ) interface { } {
v := item . ( int )
v := item . ( int )
@ -159,9 +184,11 @@ func TestGroup(t *testing.T) {
assert . Equal ( t , 2 , len ( group ) )
assert . Equal ( t , 2 , len ( group ) )
assert . True ( t , group [ 0 ] / 10 == group [ 1 ] / 10 )
assert . True ( t , group [ 0 ] / 10 == group [ 1 ] / 10 )
}
}
} )
}
}
func TestHead ( t * testing . T ) {
func TestHead ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var result int
var result int
Just ( 1 , 2 , 3 , 4 ) . Head ( 2 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
Just ( 1 , 2 , 3 , 4 ) . Head ( 2 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
for item := range pipe {
for item := range pipe {
@ -170,17 +197,21 @@ func TestHead(t *testing.T) {
return result , nil
return result , nil
} )
} )
assert . Equal ( t , 3 , result )
assert . Equal ( t , 3 , result )
} )
}
}
func TestHeadZero ( t * testing . T ) {
func TestHeadZero ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
assert . Panics ( t , func ( ) {
assert . Panics ( t , func ( ) {
Just ( 1 , 2 , 3 , 4 ) . Head ( 0 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
Just ( 1 , 2 , 3 , 4 ) . Head ( 0 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
return nil , nil
return nil , nil
} )
} )
} )
} )
} )
}
}
func TestHeadMore ( t * testing . T ) {
func TestHeadMore ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var result int
var result int
Just ( 1 , 2 , 3 , 4 ) . Head ( 6 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
Just ( 1 , 2 , 3 , 4 ) . Head ( 6 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
for item := range pipe {
for item := range pipe {
@ -189,9 +220,23 @@ func TestHeadMore(t *testing.T) {
return result , nil
return result , nil
} )
} )
assert . Equal ( t , 10 , result )
assert . Equal ( t , 10 , result )
} )
}
func TestLast ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
goroutines := runtime . NumGoroutine ( )
assert . Nil ( t , Just ( ) . Last ( ) )
assert . Equal ( t , "foo" , Just ( "foo" ) . Last ( ) )
assert . Equal ( t , "bar" , Just ( "foo" , "bar" ) . Last ( ) )
// let scheduler schedule first
runtime . Gosched ( )
assert . Equal ( t , goroutines , runtime . NumGoroutine ( ) )
} )
}
}
func TestMap ( t * testing . T ) {
func TestMap ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
log . SetOutput ( ioutil . Discard )
log . SetOutput ( ioutil . Discard )
tests := [ ] struct {
tests := [ ] struct {
@ -252,30 +297,38 @@ func TestMap(t *testing.T) {
assert . Equal ( t , test . expect , result )
assert . Equal ( t , test . expect , result )
} )
} )
}
}
} )
}
}
func TestMerge ( t * testing . T ) {
func TestMerge ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
Just ( 1 , 2 , 3 , 4 ) . Merge ( ) . ForEach ( func ( item interface { } ) {
Just ( 1 , 2 , 3 , 4 ) . Merge ( ) . ForEach ( func ( item interface { } ) {
assert . ElementsMatch ( t , [ ] interface { } { 1 , 2 , 3 , 4 } , item . ( [ ] interface { } ) )
assert . ElementsMatch ( t , [ ] interface { } { 1 , 2 , 3 , 4 } , item . ( [ ] interface { } ) )
} )
} )
} )
}
}
func TestParallelJust ( t * testing . T ) {
func TestParallelJust ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var count int32
var count int32
Just ( 1 , 2 , 3 ) . Parallel ( func ( item interface { } ) {
Just ( 1 , 2 , 3 ) . Parallel ( func ( item interface { } ) {
time . Sleep ( time . Millisecond * 100 )
time . Sleep ( time . Millisecond * 100 )
atomic . AddInt32 ( & count , int32 ( item . ( int ) ) )
atomic . AddInt32 ( & count , int32 ( item . ( int ) ) )
} , UnlimitedWorkers ( ) )
} , UnlimitedWorkers ( ) )
assert . Equal ( t , int32 ( 6 ) , count )
assert . Equal ( t , int32 ( 6 ) , count )
} )
}
}
func TestReverse ( t * testing . T ) {
func TestReverse ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
Just ( 1 , 2 , 3 , 4 ) . Reverse ( ) . Merge ( ) . ForEach ( func ( item interface { } ) {
Just ( 1 , 2 , 3 , 4 ) . Reverse ( ) . Merge ( ) . ForEach ( func ( item interface { } ) {
assert . ElementsMatch ( t , [ ] interface { } { 4 , 3 , 2 , 1 } , item . ( [ ] interface { } ) )
assert . ElementsMatch ( t , [ ] interface { } { 4 , 3 , 2 , 1 } , item . ( [ ] interface { } ) )
} )
} )
} )
}
}
func TestSort ( t * testing . T ) {
func TestSort ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var prev int
var prev int
Just ( 5 , 3 , 7 , 1 , 9 , 6 , 4 , 8 , 2 ) . Sort ( func ( a , b interface { } ) bool {
Just ( 5 , 3 , 7 , 1 , 9 , 6 , 4 , 8 , 2 ) . Sort ( func ( a , b interface { } ) bool {
return a . ( int ) < b . ( int )
return a . ( int ) < b . ( int )
@ -284,9 +337,11 @@ func TestSort(t *testing.T) {
assert . True ( t , prev < next )
assert . True ( t , prev < next )
prev = next
prev = next
} )
} )
} )
}
}
func TestSplit ( t * testing . T ) {
func TestSplit ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
assert . Panics ( t , func ( ) {
assert . Panics ( t , func ( ) {
Just ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ) . Split ( 0 ) . Done ( )
Just ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ) . Split ( 0 ) . Done ( )
} )
} )
@ -300,9 +355,11 @@ func TestSplit(t *testing.T) {
{ 5 , 6 , 7 , 8 } ,
{ 5 , 6 , 7 , 8 } ,
{ 9 , 10 } ,
{ 9 , 10 } ,
} , chunks )
} , chunks )
} )
}
}
func TestTail ( t * testing . T ) {
func TestTail ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var result int
var result int
Just ( 1 , 2 , 3 , 4 ) . Tail ( 2 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
Just ( 1 , 2 , 3 , 4 ) . Tail ( 2 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
for item := range pipe {
for item := range pipe {
@ -311,17 +368,21 @@ func TestTail(t *testing.T) {
return result , nil
return result , nil
} )
} )
assert . Equal ( t , 7 , result )
assert . Equal ( t , 7 , result )
} )
}
}
func TestTailZero ( t * testing . T ) {
func TestTailZero ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
assert . Panics ( t , func ( ) {
assert . Panics ( t , func ( ) {
Just ( 1 , 2 , 3 , 4 ) . Tail ( 0 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
Just ( 1 , 2 , 3 , 4 ) . Tail ( 0 ) . Reduce ( func ( pipe <- chan interface { } ) ( interface { } , error ) {
return nil , nil
return nil , nil
} )
} )
} )
} )
} )
}
}
func TestWalk ( t * testing . T ) {
func TestWalk ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
var result int
var result int
Just ( 1 , 2 , 3 , 4 , 5 ) . Walk ( func ( item interface { } , pipe chan <- interface { } ) {
Just ( 1 , 2 , 3 , 4 , 5 ) . Walk ( func ( item interface { } , pipe chan <- interface { } ) {
if item . ( int ) % 2 != 0 {
if item . ( int ) % 2 != 0 {
@ -331,69 +392,11 @@ func TestWalk(t *testing.T) {
result += item . ( int )
result += item . ( int )
} )
} )
assert . Equal ( t , 9 , result )
assert . Equal ( t , 9 , result )
}
func BenchmarkParallelMapReduce ( b * testing . B ) {
b . ReportAllocs ( )
mapper := func ( v interface { } ) interface { } {
return v . ( int64 ) * v . ( int64 )
}
reducer := func ( input <- chan interface { } ) ( interface { } , error ) {
var result int64
for v := range input {
result += v . ( int64 )
}
return result , nil
}
b . ResetTimer ( )
From ( func ( input chan <- interface { } ) {
b . RunParallel ( func ( pb * testing . PB ) {
for pb . Next ( ) {
input <- int64 ( rand . Int ( ) )
}
} )
} )
} ) . Map ( mapper ) . Reduce ( reducer )
}
func BenchmarkMapReduce ( b * testing . B ) {
b . ReportAllocs ( )
mapper := func ( v interface { } ) interface { } {
return v . ( int64 ) * v . ( int64 )
}
reducer := func ( input <- chan interface { } ) ( interface { } , error ) {
var result int64
for v := range input {
result += v . ( int64 )
}
return result , nil
}
b . ResetTimer ( )
From ( func ( input chan <- interface { } ) {
for i := 0 ; i < b . N ; i ++ {
input <- int64 ( rand . Int ( ) )
}
} ) . Map ( mapper ) . Reduce ( reducer )
}
func equal ( t * testing . T , stream Stream , data [ ] interface { } ) {
items := make ( [ ] interface { } , 0 )
for item := range stream . source {
items = append ( items , item )
}
if ! reflect . DeepEqual ( items , data ) {
t . Errorf ( " %v, want %v" , items , data )
}
}
func assetEqual ( t * testing . T , except , data interface { } ) {
if ! reflect . DeepEqual ( except , data ) {
t . Errorf ( " %v, want %v" , data , except )
}
}
}
func TestStream_AnyMach ( t * testing . T ) {
func TestStream_AnyMach ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
assetEqual ( t , false , Just ( 1 , 2 , 3 ) . AnyMach ( func ( item interface { } ) bool {
assetEqual ( t , false , Just ( 1 , 2 , 3 ) . AnyMach ( func ( item interface { } ) bool {
return item . ( int ) == 4
return item . ( int ) == 4
} ) )
} ) )
@ -406,9 +409,11 @@ func TestStream_AnyMach(t *testing.T) {
assetEqual ( t , true , Just ( 1 , 2 , 3 ) . AnyMach ( func ( item interface { } ) bool {
assetEqual ( t , true , Just ( 1 , 2 , 3 ) . AnyMach ( func ( item interface { } ) bool {
return item . ( int ) == 2
return item . ( int ) == 2
} ) )
} ) )
} )
}
}
func TestStream_AllMach ( t * testing . T ) {
func TestStream_AllMach ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
assetEqual (
assetEqual (
t , true , Just ( 1 , 2 , 3 ) . AllMach ( func ( item interface { } ) bool {
t , true , Just ( 1 , 2 , 3 ) . AllMach ( func ( item interface { } ) bool {
return true
return true
@ -424,9 +429,31 @@ func TestStream_AllMach(t *testing.T) {
return item . ( int ) == 1
return item . ( int ) == 1
} ) ,
} ) ,
)
)
} )
}
func TestStream_NoneMatch ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
assetEqual (
t , true , Just ( 1 , 2 , 3 ) . NoneMatch ( func ( item interface { } ) bool {
return false
} ) ,
)
assetEqual (
t , false , Just ( 1 , 2 , 3 ) . NoneMatch ( func ( item interface { } ) bool {
return true
} ) ,
)
assetEqual (
t , true , Just ( 1 , 2 , 3 ) . NoneMatch ( func ( item interface { } ) bool {
return item . ( int ) == 4
} ) ,
)
} )
}
}
func TestConcat ( t * testing . T ) {
func TestConcat ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
a1 := [ ] interface { } { 1 , 2 , 3 }
a1 := [ ] interface { } { 1 , 2 , 3 }
a2 := [ ] interface { } { 4 , 5 , 6 }
a2 := [ ] interface { } { 4 , 5 , 6 }
s1 := Just ( a1 ... )
s1 := Just ( a1 ... )
@ -443,9 +470,11 @@ func TestConcat(t *testing.T) {
ints = append ( ints , a1 ... )
ints = append ( ints , a1 ... )
ints = append ( ints , a2 ... )
ints = append ( ints , a2 ... )
assetEqual ( t , ints , items )
assetEqual ( t , ints , items )
} )
}
}
func TestStream_Skip ( t * testing . T ) {
func TestStream_Skip ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
assetEqual ( t , 3 , Just ( 1 , 2 , 3 , 4 ) . Skip ( 1 ) . Count ( ) )
assetEqual ( t , 3 , Just ( 1 , 2 , 3 , 4 ) . Skip ( 1 ) . Count ( ) )
assetEqual ( t , 1 , Just ( 1 , 2 , 3 , 4 ) . Skip ( 3 ) . Count ( ) )
assetEqual ( t , 1 , Just ( 1 , 2 , 3 , 4 ) . Skip ( 3 ) . Count ( ) )
assetEqual ( t , 4 , Just ( 1 , 2 , 3 , 4 ) . Skip ( 0 ) . Count ( ) )
assetEqual ( t , 4 , Just ( 1 , 2 , 3 , 4 ) . Skip ( 0 ) . Count ( ) )
@ -453,9 +482,11 @@ func TestStream_Skip(t *testing.T) {
assert . Panics ( t , func ( ) {
assert . Panics ( t , func ( ) {
Just ( 1 , 2 , 3 , 4 ) . Skip ( - 1 )
Just ( 1 , 2 , 3 , 4 ) . Skip ( - 1 )
} )
} )
} )
}
}
func TestStream_Concat ( t * testing . T ) {
func TestStream_Concat ( t * testing . T ) {
runCheckedTest ( t , func ( t * testing . T ) {
stream := Just ( 1 ) . Concat ( Just ( 2 ) , Just ( 3 ) )
stream := Just ( 1 ) . Concat ( Just ( 2 ) , Just ( 3 ) )
var items [ ] interface { }
var items [ ] interface { }
for item := range stream . source {
for item := range stream . source {
@ -468,4 +499,73 @@ func TestStream_Concat(t *testing.T) {
just := Just ( 1 )
just := Just ( 1 )
equal ( t , just . Concat ( just ) , [ ] interface { } { 1 } )
equal ( t , just . Concat ( just ) , [ ] interface { } { 1 } )
} )
}
func BenchmarkParallelMapReduce ( b * testing . B ) {
b . ReportAllocs ( )
mapper := func ( v interface { } ) interface { } {
return v . ( int64 ) * v . ( int64 )
}
reducer := func ( input <- chan interface { } ) ( interface { } , error ) {
var result int64
for v := range input {
result += v . ( int64 )
}
return result , nil
}
b . ResetTimer ( )
From ( func ( input chan <- interface { } ) {
b . RunParallel ( func ( pb * testing . PB ) {
for pb . Next ( ) {
input <- int64 ( rand . Int ( ) )
}
} )
} ) . Map ( mapper ) . Reduce ( reducer )
}
func BenchmarkMapReduce ( b * testing . B ) {
b . ReportAllocs ( )
mapper := func ( v interface { } ) interface { } {
return v . ( int64 ) * v . ( int64 )
}
reducer := func ( input <- chan interface { } ) ( interface { } , error ) {
var result int64
for v := range input {
result += v . ( int64 )
}
return result , nil
}
b . ResetTimer ( )
From ( func ( input chan <- interface { } ) {
for i := 0 ; i < b . N ; i ++ {
input <- int64 ( rand . Int ( ) )
}
} ) . Map ( mapper ) . Reduce ( reducer )
}
func assetEqual ( t * testing . T , except , data interface { } ) {
if ! reflect . DeepEqual ( except , data ) {
t . Errorf ( " %v, want %v" , data , except )
}
}
func equal ( t * testing . T , stream Stream , data [ ] interface { } ) {
items := make ( [ ] interface { } , 0 )
for item := range stream . source {
items = append ( items , item )
}
if ! reflect . DeepEqual ( items , data ) {
t . Errorf ( " %v, want %v" , items , data )
}
}
func runCheckedTest ( t * testing . T , fn func ( t * testing . T ) ) {
goroutines := runtime . NumGoroutine ( )
fn ( t )
// let scheduler schedule first
time . Sleep ( time . Millisecond )
assert . Equal ( t , goroutines , runtime . NumGoroutine ( ) )
}
}