// WithContext constructs and returns a Process that respects // given context. It is the equivalent of: // // func ProcessWithContext(ctx context.Context) goprocess.Process { // p := goprocess.WithParent(goprocess.Background()) // go func() { // <-ctx.Done() // p.Close() // }() // return p // } // func WithContext(ctx context.Context) goprocess.Process { if ctx == nil { panic("nil Context") } p := goprocess.WithParent(goprocess.Background()) go func() { <-ctx.Done() p.Close() }() return p }
func TestRateLimitLimitedGoBlocks(t *testing.T) { numChildren := 6 t.Logf("create a rate limiter with limit of %d", numChildren/2) rl := NewRateLimiter(process.Background(), numChildren/2) doneSpawning := make(chan struct{}) childClosing := make(chan struct{}) t.Log("spawn 6 children with LimitedGo.") go func() { for i := 0; i < numChildren; i++ { rl.LimitedGo(func(child process.Process) { // hang until we drain childClosing childClosing <- struct{}{} }) t.Logf("spawned %d", i) } close(doneSpawning) }() t.Log("should have blocked.") select { case <-doneSpawning: t.Error("did not block") case <-time.After(time.Millisecond): // for scheduler t.Log("blocked") } t.Logf("drain %d children so they close", numChildren/2) for i := 0; i < numChildren/2; i++ { t.Logf("closing %d", i) <-childClosing // consume child cloing t.Logf("closed %d", i) } t.Log("should be done spawning.") select { case <-doneSpawning: case <-time.After(time.Millisecond): // for scheduler t.Error("still blocked...") } t.Logf("drain %d children so they close", numChildren/2) for i := 0; i < numChildren/2; i++ { <-childClosing t.Logf("closed %d", i) } rl.Close() // ensure everyone's closed. }
func TestRateLimitGoDoesntBlock(t *testing.T) { numChildren := 6 t.Logf("create a rate limiter with limit of %d", numChildren/2) rl := NewRateLimiter(process.Background(), numChildren/2) doneSpawning := make(chan struct{}) childClosing := make(chan struct{}) t.Log("spawn 6 children with usual Process.Go.") go func() { for i := 0; i < numChildren; i++ { rl.Go(func(child process.Process) { // hang until we drain childClosing childClosing <- struct{}{} }) t.Logf("spawned %d", i) } close(doneSpawning) }() t.Log("should not have blocked.") select { case <-doneSpawning: t.Log("did not block") case <-time.After(time.Millisecond): // for scheduler t.Error("process.Go blocked. it should not.") } t.Log("drain children so they close") for i := 0; i < numChildren; i++ { <-childClosing t.Logf("closed %d", i) } rl.Close() // ensure everyone's closed. }