2018-05-20 18:57:48 +03:00
// MIT License
2018-05-20 16:25:59 +03:00
// Copyright (c) 2018 Andy Pan
2018-05-20 18:57:48 +03:00
2018-05-20 16:25:59 +03:00
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
2018-05-20 18:57:48 +03:00
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
2018-05-20 16:25:59 +03:00
//
2018-05-20 18:57:48 +03:00
// The above copyright notice and this permission notice shall be included in all
2018-05-20 16:25:59 +03:00
// copies or substantial portions of the Software.
//
2018-05-20 18:57:48 +03:00
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
2018-05-20 16:25:59 +03:00
2019-10-09 22:02:04 +03:00
package ants
2018-05-19 07:33:29 +03:00
2018-05-19 10:22:14 +03:00
import (
2020-03-12 19:02:19 +03:00
"log"
"os"
2018-05-20 11:22:56 +03:00
"runtime"
2018-05-20 16:29:38 +03:00
"sync"
2019-01-21 13:57:23 +03:00
"sync/atomic"
2018-05-20 16:29:38 +03:00
"testing"
2018-07-25 17:28:11 +03:00
"time"
2020-01-08 05:53:23 +03:00
"github.com/stretchr/testify/assert"
2018-05-19 10:22:14 +03:00
)
2018-10-03 15:55:39 +03:00
const (
2019-10-04 06:24:13 +03:00
_ = 1 << ( 10 * iota )
KiB // 1024
2019-01-29 15:51:34 +03:00
MiB // 1048576
2019-08-19 11:42:53 +03:00
//GiB // 1073741824
//TiB // 1099511627776 (超过了int32的范围)
//PiB // 1125899906842624
//EiB // 1152921504606846976
//ZiB // 1180591620717411303424 (超过了int64的范围)
//YiB // 1208925819614629174706176
2018-10-03 15:55:39 +03:00
)
const (
Param = 100
AntsSize = 1000
TestSize = 10000
n = 100000
)
2018-08-04 05:34:02 +03:00
var curMem uint64
2018-05-19 10:22:14 +03:00
2019-01-27 00:30:51 +03:00
// TestAntsPoolWaitToGetWorker is used to test waiting to get worker.
func TestAntsPoolWaitToGetWorker ( t * testing . T ) {
var wg sync . WaitGroup
2019-10-09 22:02:04 +03:00
p , _ := NewPool ( AntsSize )
2019-01-27 00:30:51 +03:00
defer p . Release ( )
for i := 0 ; i < n ; i ++ {
wg . Add ( 1 )
2019-08-19 11:42:53 +03:00
_ = p . Submit ( func ( ) {
2019-01-27 00:30:51 +03:00
demoPoolFunc ( Param )
wg . Done ( )
} )
}
wg . Wait ( )
t . Logf ( "pool, running workers number:%d" , p . Running ( ) )
mem := runtime . MemStats { }
runtime . ReadMemStats ( & mem )
curMem = mem . TotalAlloc / MiB - curMem
t . Logf ( "memory usage:%d MB" , curMem )
}
2019-07-26 09:25:16 +03:00
func TestAntsPoolWaitToGetWorkerPreMalloc ( t * testing . T ) {
var wg sync . WaitGroup
2019-10-09 22:02:04 +03:00
p , _ := NewPool ( AntsSize , WithPreAlloc ( true ) )
2019-07-26 09:25:16 +03:00
defer p . Release ( )
for i := 0 ; i < n ; i ++ {
wg . Add ( 1 )
2019-08-19 11:42:53 +03:00
_ = p . Submit ( func ( ) {
2019-07-26 09:25:16 +03:00
demoPoolFunc ( Param )
wg . Done ( )
} )
}
wg . Wait ( )
t . Logf ( "pool, running workers number:%d" , p . Running ( ) )
mem := runtime . MemStats { }
runtime . ReadMemStats ( & mem )
curMem = mem . TotalAlloc / MiB - curMem
t . Logf ( "memory usage:%d MB" , curMem )
}
2019-01-26 22:14:47 +03:00
// TestAntsPoolWithFuncWaitToGetWorker is used to test waiting to get worker.
func TestAntsPoolWithFuncWaitToGetWorker ( t * testing . T ) {
2018-07-15 15:50:10 +03:00
var wg sync . WaitGroup
2019-10-09 22:02:04 +03:00
p , _ := NewPoolWithFunc ( AntsSize , func ( i interface { } ) {
2018-07-15 15:50:10 +03:00
demoPoolFunc ( i )
wg . Done ( )
} )
defer p . Release ( )
for i := 0 ; i < n ; i ++ {
wg . Add ( 1 )
2019-08-19 11:42:53 +03:00
_ = p . Invoke ( Param )
2018-07-15 15:50:10 +03:00
}
wg . Wait ( )
2018-07-15 18:34:12 +03:00
t . Logf ( "pool with func, running workers number:%d" , p . Running ( ) )
2018-07-15 15:50:10 +03:00
mem := runtime . MemStats { }
runtime . ReadMemStats ( & mem )
2018-10-03 15:55:39 +03:00
curMem = mem . TotalAlloc / MiB - curMem
2018-09-28 15:10:59 +03:00
t . Logf ( "memory usage:%d MB" , curMem )
2018-07-15 15:50:10 +03:00
}
2018-12-03 09:31:49 +03:00
2019-07-26 09:25:16 +03:00
func TestAntsPoolWithFuncWaitToGetWorkerPreMalloc ( t * testing . T ) {
var wg sync . WaitGroup
2019-10-09 22:02:04 +03:00
p , _ := NewPoolWithFunc ( AntsSize , func ( i interface { } ) {
2019-07-26 09:25:16 +03:00
demoPoolFunc ( i )
wg . Done ( )
2019-10-09 22:02:04 +03:00
} , WithPreAlloc ( true ) )
2019-07-26 09:25:16 +03:00
defer p . Release ( )
for i := 0 ; i < n ; i ++ {
wg . Add ( 1 )
2019-08-19 11:42:53 +03:00
_ = p . Invoke ( Param )
2019-07-26 09:25:16 +03:00
}
wg . Wait ( )
t . Logf ( "pool with func, running workers number:%d" , p . Running ( ) )
mem := runtime . MemStats { }
runtime . ReadMemStats ( & mem )
curMem = mem . TotalAlloc / MiB - curMem
t . Logf ( "memory usage:%d MB" , curMem )
}
2019-04-14 05:37:53 +03:00
// TestAntsPoolGetWorkerFromCache is used to test getting worker from sync.Pool.
2019-04-13 06:15:09 +03:00
func TestAntsPoolGetWorkerFromCache ( t * testing . T ) {
2019-10-09 22:02:04 +03:00
p , _ := NewPool ( TestSize )
2019-04-13 06:15:09 +03:00
defer p . Release ( )
for i := 0 ; i < AntsSize ; i ++ {
2019-08-19 11:42:53 +03:00
_ = p . Submit ( demoFunc )
2019-04-13 06:15:09 +03:00
}
2019-10-09 22:02:04 +03:00
time . Sleep ( 2 * DefaultCleanIntervalTime )
2019-08-19 11:42:53 +03:00
_ = p . Submit ( demoFunc )
2019-04-13 06:15:09 +03:00
t . Logf ( "pool, running workers number:%d" , p . Running ( ) )
mem := runtime . MemStats { }
runtime . ReadMemStats ( & mem )
curMem = mem . TotalAlloc / MiB - curMem
t . Logf ( "memory usage:%d MB" , curMem )
}
2019-04-14 05:37:53 +03:00
// TestAntsPoolWithFuncGetWorkerFromCache is used to test getting worker from sync.Pool.
2019-04-13 06:15:09 +03:00
func TestAntsPoolWithFuncGetWorkerFromCache ( t * testing . T ) {
dur := 10
2019-10-09 22:02:04 +03:00
p , _ := NewPoolWithFunc ( TestSize , demoPoolFunc )
2019-04-13 06:15:09 +03:00
defer p . Release ( )
for i := 0 ; i < AntsSize ; i ++ {
2019-08-19 11:42:53 +03:00
_ = p . Invoke ( dur )
2019-04-13 06:15:09 +03:00
}
2019-10-09 22:02:04 +03:00
time . Sleep ( 2 * DefaultCleanIntervalTime )
2019-08-19 11:42:53 +03:00
_ = p . Invoke ( dur )
2019-04-13 06:15:09 +03:00
t . Logf ( "pool with func, running workers number:%d" , p . Running ( ) )
mem := runtime . MemStats { }
runtime . ReadMemStats ( & mem )
curMem = mem . TotalAlloc / MiB - curMem
t . Logf ( "memory usage:%d MB" , curMem )
}
2019-01-26 21:32:37 +03:00
2019-07-26 09:25:16 +03:00
func TestAntsPoolWithFuncGetWorkerFromCachePreMalloc ( t * testing . T ) {
dur := 10
2019-10-09 22:02:04 +03:00
p , _ := NewPoolWithFunc ( TestSize , demoPoolFunc , WithPreAlloc ( true ) )
2019-07-26 09:25:16 +03:00
defer p . Release ( )
for i := 0 ; i < AntsSize ; i ++ {
2019-08-19 11:42:53 +03:00
_ = p . Invoke ( dur )
2019-07-26 09:25:16 +03:00
}
2019-10-09 22:02:04 +03:00
time . Sleep ( 2 * DefaultCleanIntervalTime )
2019-08-19 11:42:53 +03:00
_ = p . Invoke ( dur )
2019-07-26 09:25:16 +03:00
t . Logf ( "pool with func, running workers number:%d" , p . Running ( ) )
mem := runtime . MemStats { }
runtime . ReadMemStats ( & mem )
curMem = mem . TotalAlloc / MiB - curMem
t . Logf ( "memory usage:%d MB" , curMem )
}
2019-01-26 21:32:37 +03:00
//-------------------------------------------------------------------------------------------
// Contrast between goroutines without a pool and goroutines with ants pool.
//-------------------------------------------------------------------------------------------
2018-08-04 05:34:02 +03:00
func TestNoPool ( t * testing . T ) {
2018-05-20 06:51:14 +03:00
var wg sync . WaitGroup
2018-05-19 10:22:14 +03:00
for i := 0 ; i < n ; i ++ {
2018-05-20 06:51:14 +03:00
wg . Add ( 1 )
2018-08-04 05:34:02 +03:00
go func ( ) {
2018-05-23 12:21:39 +03:00
demoFunc ( )
wg . Done ( )
2018-08-04 05:34:02 +03:00
} ( )
2018-05-19 10:22:14 +03:00
}
2018-07-15 17:45:55 +03:00
2018-08-04 05:34:02 +03:00
wg . Wait ( )
2018-05-19 15:16:33 +03:00
mem := runtime . MemStats { }
runtime . ReadMemStats ( & mem )
2018-08-04 05:34:02 +03:00
curMem = mem . TotalAlloc / MiB - curMem
t . Logf ( "memory usage:%d MB" , curMem )
2018-05-19 10:22:14 +03:00
}
2018-08-04 05:34:02 +03:00
func TestAntsPool ( t * testing . T ) {
2019-10-09 22:02:04 +03:00
defer Release ( )
2018-05-20 11:22:56 +03:00
var wg sync . WaitGroup
for i := 0 ; i < n ; i ++ {
wg . Add ( 1 )
2019-10-09 22:02:04 +03:00
_ = Submit ( func ( ) {
2018-05-23 12:21:39 +03:00
demoFunc ( )
2018-05-20 11:22:56 +03:00
wg . Done ( )
2018-08-04 05:34:02 +03:00
} )
2018-05-20 11:22:56 +03:00
}
2018-05-22 06:17:19 +03:00
wg . Wait ( )
2018-08-04 05:34:02 +03:00
2019-10-09 22:02:04 +03:00
t . Logf ( "pool, capacity:%d" , Cap ( ) )
t . Logf ( "pool, running workers number:%d" , Running ( ) )
t . Logf ( "pool, free workers number:%d" , Free ( ) )
2018-08-04 05:34:02 +03:00
2018-05-20 11:22:56 +03:00
mem := runtime . MemStats { }
runtime . ReadMemStats ( & mem )
2018-08-04 05:34:02 +03:00
curMem = mem . TotalAlloc / MiB - curMem
t . Logf ( "memory usage:%d MB" , curMem )
2018-05-23 12:21:39 +03:00
}
2019-01-26 21:32:37 +03:00
//-------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------
2019-01-21 13:57:23 +03:00
func TestPanicHandler ( t * testing . T ) {
var panicCounter int64
var wg sync . WaitGroup
2019-10-09 22:02:04 +03:00
p0 , err := NewPool ( 10 , WithPanicHandler ( func ( p interface { } ) {
2019-01-21 13:57:23 +03:00
defer wg . Done ( )
atomic . AddInt64 ( & panicCounter , 1 )
2019-01-26 19:06:32 +03:00
t . Logf ( "catch panic with PanicHandler: %v" , p )
2019-08-21 17:07:19 +03:00
} ) )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create new pool failed: %v" , err )
2019-08-21 17:07:19 +03:00
defer p0 . Release ( )
2019-01-21 13:57:23 +03:00
wg . Add ( 1 )
2019-08-19 11:42:53 +03:00
_ = p0 . Submit ( func ( ) {
2019-01-26 19:06:32 +03:00
panic ( "Oops!" )
2019-01-21 13:57:23 +03:00
} )
wg . Wait ( )
c := atomic . LoadInt64 ( & panicCounter )
2020-01-08 05:53:23 +03:00
assert . EqualValuesf ( t , 1 , c , "panic handler didn't work, panicCounter: %d" , c )
assert . EqualValues ( t , 0 , p0 . Running ( ) , "pool should be empty after panic" )
2019-10-09 22:02:04 +03:00
p1 , err := NewPoolWithFunc ( 10 , func ( p interface { } ) { panic ( p ) } , WithPanicHandler ( func ( p interface { } ) {
2019-08-21 17:07:19 +03:00
defer wg . Done ( )
atomic . AddInt64 ( & panicCounter , 1 )
} ) )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create new pool with func failed: %v" , err )
2019-01-21 13:57:23 +03:00
defer p1 . Release ( )
wg . Add ( 1 )
2019-08-19 11:42:53 +03:00
_ = p1 . Invoke ( "Oops!" )
2019-01-21 13:57:23 +03:00
wg . Wait ( )
c = atomic . LoadInt64 ( & panicCounter )
2020-01-08 05:53:23 +03:00
assert . EqualValuesf ( t , 2 , c , "panic handler didn't work, panicCounter: %d" , c )
assert . EqualValues ( t , 0 , p1 . Running ( ) , "pool should be empty after panic" )
2019-01-21 13:57:23 +03:00
}
2019-07-26 09:25:16 +03:00
func TestPanicHandlerPreMalloc ( t * testing . T ) {
var panicCounter int64
var wg sync . WaitGroup
2019-10-09 22:02:04 +03:00
p0 , err := NewPool ( 10 , WithPreAlloc ( true ) , WithPanicHandler ( func ( p interface { } ) {
2019-07-26 09:25:16 +03:00
defer wg . Done ( )
atomic . AddInt64 ( & panicCounter , 1 )
t . Logf ( "catch panic with PanicHandler: %v" , p )
2019-08-21 17:07:19 +03:00
} ) )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create new pool failed: %v" , err )
2019-08-21 17:07:19 +03:00
defer p0 . Release ( )
2019-07-26 09:25:16 +03:00
wg . Add ( 1 )
2019-08-19 11:42:53 +03:00
_ = p0 . Submit ( func ( ) {
2019-07-26 09:25:16 +03:00
panic ( "Oops!" )
} )
wg . Wait ( )
c := atomic . LoadInt64 ( & panicCounter )
2020-01-08 05:53:23 +03:00
assert . EqualValuesf ( t , 1 , c , "panic handler didn't work, panicCounter: %d" , c )
assert . EqualValues ( t , 0 , p0 . Running ( ) , "pool should be empty after panic" )
2019-10-09 22:02:04 +03:00
p1 , err := NewPoolWithFunc ( 10 , func ( p interface { } ) { panic ( p ) } , WithPanicHandler ( func ( p interface { } ) {
2019-08-21 17:07:19 +03:00
defer wg . Done ( )
atomic . AddInt64 ( & panicCounter , 1 )
} ) )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create new pool with func failed: %v" , err )
2019-07-26 09:25:16 +03:00
defer p1 . Release ( )
wg . Add ( 1 )
2019-08-19 11:42:53 +03:00
_ = p1 . Invoke ( "Oops!" )
2019-07-26 09:25:16 +03:00
wg . Wait ( )
c = atomic . LoadInt64 ( & panicCounter )
2020-01-08 05:53:23 +03:00
assert . EqualValuesf ( t , 2 , c , "panic handler didn't work, panicCounter: %d" , c )
assert . EqualValues ( t , 0 , p1 . Running ( ) , "pool should be empty after panic" )
2019-07-26 09:25:16 +03:00
}
2019-01-26 19:06:32 +03:00
func TestPoolPanicWithoutHandler ( t * testing . T ) {
2019-10-09 22:02:04 +03:00
p0 , err := NewPool ( 10 )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create new pool failed: %v" , err )
2019-01-26 19:06:32 +03:00
defer p0 . Release ( )
2019-08-19 11:42:53 +03:00
_ = p0 . Submit ( func ( ) {
2019-01-26 19:06:32 +03:00
panic ( "Oops!" )
} )
2019-10-09 22:02:04 +03:00
p1 , err := NewPoolWithFunc ( 10 , func ( p interface { } ) {
2019-01-26 19:06:32 +03:00
panic ( p )
} )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create new pool with func failed: %v" , err )
2019-01-26 19:06:32 +03:00
defer p1 . Release ( )
2019-08-19 11:42:53 +03:00
_ = p1 . Invoke ( "Oops!" )
2019-01-26 19:06:32 +03:00
}
2019-07-26 09:25:16 +03:00
func TestPoolPanicWithoutHandlerPreMalloc ( t * testing . T ) {
2019-10-09 22:02:04 +03:00
p0 , err := NewPool ( 10 , WithPreAlloc ( true ) )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create new pool failed: %v" , err )
2019-07-26 09:25:16 +03:00
defer p0 . Release ( )
2019-08-19 11:42:53 +03:00
_ = p0 . Submit ( func ( ) {
2019-07-26 09:25:16 +03:00
panic ( "Oops!" )
} )
2019-10-09 22:02:04 +03:00
p1 , err := NewPoolWithFunc ( 10 , func ( p interface { } ) {
2019-07-26 09:25:16 +03:00
panic ( p )
} )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create new pool with func failed: %v" , err )
2019-07-26 09:25:16 +03:00
defer p1 . Release ( )
2019-08-19 11:42:53 +03:00
_ = p1 . Invoke ( "Oops!" )
2019-07-26 09:25:16 +03:00
}
2019-01-26 21:32:37 +03:00
func TestPurge ( t * testing . T ) {
2019-10-09 22:02:04 +03:00
p , err := NewPool ( 10 )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create TimingPool failed: %v" , err )
2019-08-19 11:42:53 +03:00
defer p . Release ( )
_ = p . Submit ( demoFunc )
2019-10-09 22:02:04 +03:00
time . Sleep ( 3 * DefaultCleanIntervalTime )
2020-01-08 05:53:23 +03:00
assert . EqualValues ( t , 0 , p . Running ( ) , "all p should be purged" )
2019-10-09 22:02:04 +03:00
p1 , err := NewPoolWithFunc ( 10 , demoPoolFunc )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create TimingPoolWithFunc failed: %v" , err )
2019-08-19 11:42:53 +03:00
defer p1 . Release ( )
_ = p1 . Invoke ( 1 )
2019-10-09 22:02:04 +03:00
time . Sleep ( 3 * DefaultCleanIntervalTime )
2020-01-08 05:53:23 +03:00
assert . EqualValues ( t , 0 , p . Running ( ) , "all p should be purged" )
2019-01-26 21:32:37 +03:00
}
2019-07-26 09:25:16 +03:00
func TestPurgePreMalloc ( t * testing . T ) {
2019-10-09 22:02:04 +03:00
p , err := NewPool ( 10 , WithPreAlloc ( true ) )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create TimingPool failed: %v" , err )
2019-08-19 11:42:53 +03:00
defer p . Release ( )
_ = p . Submit ( demoFunc )
2019-10-09 22:02:04 +03:00
time . Sleep ( 3 * DefaultCleanIntervalTime )
2020-01-08 05:53:23 +03:00
assert . EqualValues ( t , 0 , p . Running ( ) , "all p should be purged" )
2019-10-09 22:02:04 +03:00
p1 , err := NewPoolWithFunc ( 10 , demoPoolFunc )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create TimingPoolWithFunc failed: %v" , err )
2019-08-19 11:42:53 +03:00
defer p1 . Release ( )
_ = p1 . Invoke ( 1 )
2019-10-09 22:02:04 +03:00
time . Sleep ( 3 * DefaultCleanIntervalTime )
2020-01-08 05:53:23 +03:00
assert . EqualValues ( t , 0 , p . Running ( ) , "all p should be purged" )
2019-07-26 09:25:16 +03:00
}
2019-08-20 06:22:00 +03:00
func TestNonblockingSubmit ( t * testing . T ) {
poolSize := 10
2019-10-09 22:02:04 +03:00
p , err := NewPool ( poolSize , WithNonblocking ( true ) )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create TimingPool failed: %v" , err )
2019-08-20 06:22:00 +03:00
defer p . Release ( )
for i := 0 ; i < poolSize - 1 ; i ++ {
2020-01-08 05:53:23 +03:00
assert . NoError ( t , p . Submit ( longRunningFunc ) , "nonblocking submit when pool is not full shouldn't return error" )
2019-08-20 06:22:00 +03:00
}
ch := make ( chan struct { } )
2019-10-04 06:36:11 +03:00
ch1 := make ( chan struct { } )
2019-08-20 06:22:00 +03:00
f := func ( ) {
<- ch
2019-10-04 06:36:11 +03:00
close ( ch1 )
2019-08-20 06:22:00 +03:00
}
// p is full now.
2020-01-08 05:53:23 +03:00
assert . NoError ( t , p . Submit ( f ) , "nonblocking submit when pool is not full shouldn't return error" )
assert . EqualError ( t , p . Submit ( demoFunc ) , ErrPoolOverload . Error ( ) , "nonblocking submit when pool is full should get an ErrPoolOverload" )
2019-08-20 06:22:00 +03:00
// interrupt f to get an available worker
close ( ch )
2019-10-04 06:36:11 +03:00
<- ch1
2020-01-08 05:53:23 +03:00
assert . NoError ( t , p . Submit ( demoFunc ) , "nonblocking submit when pool is not full shouldn't return error" )
2019-08-20 06:22:00 +03:00
}
func TestMaxBlockingSubmit ( t * testing . T ) {
poolSize := 10
2019-10-09 22:02:04 +03:00
p , err := NewPool ( poolSize , WithMaxBlockingTasks ( 1 ) )
2020-01-08 05:53:23 +03:00
assert . NoErrorf ( t , err , "create TimingPool failed: %v" , err )
2019-08-20 06:22:00 +03:00
defer p . Release ( )
for i := 0 ; i < poolSize - 1 ; i ++ {
2020-01-08 05:53:23 +03:00
assert . NoError ( t , p . Submit ( longRunningFunc ) , "submit when pool is not full shouldn't return error" )
2019-08-20 06:22:00 +03:00
}
ch := make ( chan struct { } )
f := func ( ) {
<- ch
}
// p is full now.
2020-01-08 05:53:23 +03:00
assert . NoError ( t , p . Submit ( f ) , "submit when pool is not full shouldn't return error" )
2019-08-20 06:22:00 +03:00
var wg sync . WaitGroup
wg . Add ( 1 )
errCh := make ( chan error , 1 )
go func ( ) {
// should be blocked. blocking num == 1
if err := p . Submit ( demoFunc ) ; err != nil {
errCh <- err
}
wg . Done ( )
} ( )
time . Sleep ( 1 * time . Second )
// already reached max blocking limit
2020-01-08 05:53:23 +03:00
assert . EqualError ( t , p . Submit ( demoFunc ) , ErrPoolOverload . Error ( ) , "blocking submit when pool reach max blocking submit should return ErrPoolOverload" )
2019-08-20 06:22:00 +03:00
// interrupt f to make blocking submit successful.
close ( ch )
wg . Wait ( )
select {
case <- errCh :
t . Fatalf ( "blocking submit when pool is full should not return error" )
default :
}
}
func TestNonblockingSubmitWithFunc ( t * testing . T ) {
poolSize := 10
2019-10-10 17:05:42 +03:00
ch1 := make ( chan struct { } )
p , err := NewPoolWithFunc ( poolSize , func ( i interface { } ) {
longRunningPoolFunc ( i )
close ( ch1 )
} , WithNonblocking ( true ) )
2020-01-08 05:53:23 +03:00
assert . NoError ( t , err , "create TimingPool failed: %v" , err )
2019-08-20 06:22:00 +03:00
defer p . Release ( )
for i := 0 ; i < poolSize - 1 ; i ++ {
2020-01-08 05:53:23 +03:00
assert . NoError ( t , p . Invoke ( nil ) , "nonblocking submit when pool is not full shouldn't return error" )
2019-08-20 06:22:00 +03:00
}
ch := make ( chan struct { } )
// p is full now.
2020-01-08 05:53:23 +03:00
assert . NoError ( t , p . Invoke ( ch ) , "nonblocking submit when pool is not full shouldn't return error" )
assert . EqualError ( t , p . Invoke ( nil ) , ErrPoolOverload . Error ( ) , "nonblocking submit when pool is full should get an ErrPoolOverload" )
2019-08-20 06:22:00 +03:00
// interrupt f to get an available worker
close ( ch )
2019-10-10 17:05:42 +03:00
<- ch1
2020-01-08 05:53:23 +03:00
assert . NoError ( t , p . Invoke ( nil ) , "nonblocking submit when pool is not full shouldn't return error" )
2019-08-20 06:22:00 +03:00
}
func TestMaxBlockingSubmitWithFunc ( t * testing . T ) {
poolSize := 10
2019-10-09 22:02:04 +03:00
p , err := NewPoolWithFunc ( poolSize , longRunningPoolFunc , WithMaxBlockingTasks ( 1 ) )
2020-01-08 05:53:23 +03:00
assert . NoError ( t , err , "create TimingPool failed: %v" , err )
2019-08-20 06:22:00 +03:00
defer p . Release ( )
for i := 0 ; i < poolSize - 1 ; i ++ {
2020-01-08 05:53:23 +03:00
assert . NoError ( t , p . Invoke ( Param ) , "submit when pool is not full shouldn't return error" )
2019-08-20 06:22:00 +03:00
}
ch := make ( chan struct { } )
// p is full now.
2020-01-08 05:53:23 +03:00
assert . NoError ( t , p . Invoke ( ch ) , "submit when pool is not full shouldn't return error" )
2019-08-20 06:22:00 +03:00
var wg sync . WaitGroup
wg . Add ( 1 )
errCh := make ( chan error , 1 )
go func ( ) {
// should be blocked. blocking num == 1
if err := p . Invoke ( Param ) ; err != nil {
errCh <- err
}
wg . Done ( )
} ( )
time . Sleep ( 1 * time . Second )
// already reached max blocking limit
2020-01-08 05:53:23 +03:00
assert . EqualErrorf ( t , p . Invoke ( Param ) , ErrPoolOverload . Error ( ) , "blocking submit when pool reach max blocking submit should return ErrPoolOverload: %v" , err )
2019-08-20 06:22:00 +03:00
// interrupt one func to make blocking submit successful.
close ( ch )
wg . Wait ( )
select {
case <- errCh :
t . Fatalf ( "blocking submit when pool is full should not return error" )
default :
}
}
2020-01-16 07:30:35 +03:00
func TestRebootDefaultPool ( t * testing . T ) {
defer Release ( )
Reboot ( )
var wg sync . WaitGroup
wg . Add ( 1 )
_ = Submit ( func ( ) {
demoFunc ( )
wg . Done ( )
} )
wg . Wait ( )
Release ( )
assert . EqualError ( t , Submit ( nil ) , ErrPoolClosed . Error ( ) , "pool should be closed" )
Reboot ( )
wg . Add ( 1 )
assert . NoError ( t , Submit ( func ( ) { wg . Done ( ) } ) , "pool should be rebooted" )
wg . Wait ( )
}
func TestRebootNewPool ( t * testing . T ) {
var wg sync . WaitGroup
p , err := NewPool ( 10 )
assert . NoErrorf ( t , err , "create Pool failed: %v" , err )
defer p . Release ( )
wg . Add ( 1 )
_ = p . Submit ( func ( ) {
demoFunc ( )
wg . Done ( )
} )
wg . Wait ( )
p . Release ( )
assert . EqualError ( t , p . Submit ( nil ) , ErrPoolClosed . Error ( ) , "pool should be closed" )
p . Reboot ( )
wg . Add ( 1 )
assert . NoError ( t , p . Submit ( func ( ) { wg . Done ( ) } ) , "pool should be rebooted" )
wg . Wait ( )
p1 , err := NewPoolWithFunc ( 10 , func ( i interface { } ) {
demoPoolFunc ( i )
wg . Done ( )
} )
assert . NoErrorf ( t , err , "create TimingPoolWithFunc failed: %v" , err )
defer p1 . Release ( )
wg . Add ( 1 )
_ = p1 . Invoke ( 1 )
wg . Wait ( )
p1 . Release ( )
assert . EqualError ( t , p1 . Invoke ( nil ) , ErrPoolClosed . Error ( ) , "pool should be closed" )
p1 . Reboot ( )
wg . Add ( 1 )
assert . NoError ( t , p1 . Invoke ( 1 ) , "pool should be rebooted" )
wg . Wait ( )
}
2019-01-26 21:32:37 +03:00
func TestRestCodeCoverage ( t * testing . T ) {
2019-10-09 22:02:04 +03:00
_ , err := NewPool ( - 1 , WithExpiryDuration ( - 1 ) )
2018-07-15 17:45:55 +03:00
t . Log ( err )
2019-10-09 22:02:04 +03:00
_ , err = NewPool ( 1 , WithExpiryDuration ( - 1 ) )
2018-07-15 17:45:55 +03:00
t . Log ( err )
2019-10-09 22:02:04 +03:00
_ , err = NewPoolWithFunc ( - 1 , demoPoolFunc , WithExpiryDuration ( - 1 ) )
2018-07-15 17:45:55 +03:00
t . Log ( err )
2019-10-09 22:02:04 +03:00
_ , err = NewPoolWithFunc ( 1 , demoPoolFunc , WithExpiryDuration ( - 1 ) )
2018-07-15 17:45:55 +03:00
t . Log ( err )
2019-10-09 22:02:04 +03:00
options := Options { }
2019-08-21 17:07:19 +03:00
options . ExpiryDuration = time . Duration ( 10 ) * time . Second
options . Nonblocking = true
options . PreAlloc = true
2019-10-09 22:02:04 +03:00
poolOpts , _ := NewPool ( 1 , WithOptions ( options ) )
2019-08-21 17:07:19 +03:00
t . Logf ( "Pool with options, capacity: %d" , poolOpts . Cap ( ) )
2020-03-12 19:02:19 +03:00
p0 , _ := NewPool ( TestSize , WithLogger ( log . New ( os . Stderr , "" , log . LstdFlags ) ) )
2019-08-19 11:42:53 +03:00
defer func ( ) {
_ = p0 . Submit ( demoFunc )
} ( )
2018-07-15 16:27:45 +03:00
defer p0 . Release ( )
2018-07-15 15:50:10 +03:00
for i := 0 ; i < n ; i ++ {
2019-08-19 11:42:53 +03:00
_ = p0 . Submit ( demoFunc )
2018-07-15 15:50:10 +03:00
}
2018-07-15 16:27:45 +03:00
t . Logf ( "pool, capacity:%d" , p0 . Cap ( ) )
t . Logf ( "pool, running workers number:%d" , p0 . Running ( ) )
t . Logf ( "pool, free workers number:%d" , p0 . Free ( ) )
2019-01-26 23:05:58 +03:00
p0 . Tune ( TestSize )
2019-02-22 19:46:49 +03:00
p0 . Tune ( TestSize / 10 )
2019-01-26 19:06:32 +03:00
t . Logf ( "pool, after tuning capacity, capacity:%d, running:%d" , p0 . Cap ( ) , p0 . Running ( ) )
2018-05-23 12:21:39 +03:00
2019-10-09 22:02:04 +03:00
pprem , _ := NewPool ( TestSize , WithPreAlloc ( true ) )
2019-08-19 11:42:53 +03:00
defer func ( ) {
_ = pprem . Submit ( demoFunc )
} ( )
2019-07-26 09:25:16 +03:00
defer pprem . Release ( )
for i := 0 ; i < n ; i ++ {
2019-08-19 11:42:53 +03:00
_ = pprem . Submit ( demoFunc )
2019-07-26 09:25:16 +03:00
}
2019-07-27 06:14:01 +03:00
t . Logf ( "pre-malloc pool, capacity:%d" , pprem . Cap ( ) )
t . Logf ( "pre-malloc pool, running workers number:%d" , pprem . Running ( ) )
t . Logf ( "pre-malloc pool, free workers number:%d" , pprem . Free ( ) )
2019-07-26 09:25:16 +03:00
pprem . Tune ( TestSize )
pprem . Tune ( TestSize / 10 )
2019-07-27 06:14:01 +03:00
t . Logf ( "pre-malloc pool, after tuning capacity, capacity:%d, running:%d" , pprem . Cap ( ) , pprem . Running ( ) )
2019-07-26 09:25:16 +03:00
2019-10-09 22:02:04 +03:00
p , _ := NewPoolWithFunc ( TestSize , demoPoolFunc )
2019-08-19 11:42:53 +03:00
defer func ( ) {
_ = p . Invoke ( Param )
} ( )
2018-07-15 15:50:10 +03:00
defer p . Release ( )
for i := 0 ; i < n ; i ++ {
2019-08-19 11:42:53 +03:00
_ = p . Invoke ( Param )
2018-07-15 15:50:10 +03:00
}
2019-10-09 22:02:04 +03:00
time . Sleep ( DefaultCleanIntervalTime )
2018-07-15 15:50:10 +03:00
t . Logf ( "pool with func, capacity:%d" , p . Cap ( ) )
t . Logf ( "pool with func, running workers number:%d" , p . Running ( ) )
t . Logf ( "pool with func, free workers number:%d" , p . Free ( ) )
2019-01-26 19:06:32 +03:00
p . Tune ( TestSize )
2019-02-22 19:46:49 +03:00
p . Tune ( TestSize / 10 )
2019-01-26 19:06:32 +03:00
t . Logf ( "pool with func, after tuning capacity, capacity:%d, running:%d" , p . Cap ( ) , p . Running ( ) )
2019-07-26 09:25:16 +03:00
2019-10-09 22:02:04 +03:00
ppremWithFunc , _ := NewPoolWithFunc ( TestSize , demoPoolFunc , WithPreAlloc ( true ) )
2019-08-19 11:42:53 +03:00
defer func ( ) {
_ = ppremWithFunc . Invoke ( Param )
} ( )
2019-07-26 09:25:16 +03:00
defer ppremWithFunc . Release ( )
for i := 0 ; i < n ; i ++ {
2019-08-19 11:42:53 +03:00
_ = ppremWithFunc . Invoke ( Param )
2019-07-26 09:25:16 +03:00
}
2019-10-09 22:02:04 +03:00
time . Sleep ( DefaultCleanIntervalTime )
2019-07-27 06:14:01 +03:00
t . Logf ( "pre-malloc pool with func, capacity:%d" , ppremWithFunc . Cap ( ) )
t . Logf ( "pre-malloc pool with func, running workers number:%d" , ppremWithFunc . Running ( ) )
t . Logf ( "pre-malloc pool with func, free workers number:%d" , ppremWithFunc . Free ( ) )
2019-07-26 09:25:16 +03:00
ppremWithFunc . Tune ( TestSize )
ppremWithFunc . Tune ( TestSize / 10 )
2019-07-27 06:14:01 +03:00
t . Logf ( "pre-malloc pool with func, after tuning capacity, capacity:%d, running:%d" , ppremWithFunc . Cap ( ) ,
ppremWithFunc . Running ( ) )
2018-10-03 15:55:39 +03:00
}