github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/limit/limiter_test.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package limit 12 13 import ( 14 "context" 15 "runtime" 16 "sync/atomic" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 20 "github.com/cockroachdb/errors" 21 "golang.org/x/sync/errgroup" 22 ) 23 24 func TestConcurrentRequestLimiter(t *testing.T) { 25 defer leaktest.AfterTest(t)() 26 27 l := MakeConcurrentRequestLimiter("test", 1) 28 var wg errgroup.Group 29 30 const threads = 20 31 const runs = 1000000 32 var count int64 33 34 ctx, cancel := context.WithCancel(context.Background()) 35 defer cancel() 36 37 for thread := 0; thread < threads; thread++ { 38 wg.Go(func() error { 39 runtime.Gosched() 40 req := 0 41 for { 42 //t.Logf("waiting to make request %d... (%d / %d)", req+1, l.sem.GetCount(), l.sem.GetLimit()) 43 if err := l.Begin(ctx); err != nil { 44 if errors.Is(err, ctx.Err()) { 45 break 46 } else { 47 return err 48 } 49 } 50 if x := atomic.AddInt64(&count, 1); x >= runs { 51 t.Logf("canceling ctx after %d runs", x) 52 cancel() 53 } 54 req++ 55 l.Finish() 56 } 57 t.Logf("thread done after handling %d requests", req) 58 return nil 59 }) 60 } 61 if err := wg.Wait(); err != nil { 62 t.Fatal(err) 63 } 64 }