github.com/searKing/golang/go@v1.2.117/sync/until_test.go (about) 1 // Copyright 2021 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sync_test 6 7 import ( 8 "context" 9 "errors" 10 "fmt" 11 "sync" 12 "sync/atomic" 13 "testing" 14 "time" 15 16 sync_ "github.com/searKing/golang/go/sync" 17 ) 18 19 const goroutineCount = 5 20 21 func TestUntil_DoTimeout(t *testing.T) { 22 var until sync_.Until 23 ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) 24 defer cancel() 25 if _, err := until.Do(ctx, func() (any, error) { return "bar", fmt.Errorf("must error") }); !errors.Is(err, context.DeadlineExceeded) { 26 t.Errorf("until.Do returned error %v, want DeadlineExceeded", err) 27 } 28 } 29 30 func TestUntil_DoBlocking(t *testing.T) { 31 var until sync_.Until 32 // All goroutines should block because picker is nil in until. 33 var finishedCount uint64 34 for i := goroutineCount; i > 0; i-- { 35 go func() { 36 if _, err := until.Do(context.Background(), nil); err == nil { 37 t.Errorf("until.Do returned nil error") 38 } 39 atomic.AddUint64(&finishedCount, 1) 40 }() 41 } 42 time.Sleep(50 * time.Millisecond) 43 if c := atomic.LoadUint64(&finishedCount); c != 0 { 44 t.Errorf("finished goroutines count: %v, want 0", c) 45 } 46 until.Close() 47 } 48 49 func TestUntil_Do(t *testing.T) { 50 var until sync_.Until 51 // All goroutines should block because picker is nil in until. 52 var finishedCount uint64 53 for i := goroutineCount; i > 0; i-- { 54 go func() { 55 if tr, err := until.Do(context.Background(), func() (any, error) { 56 return "bar", nil 57 }); err != nil || tr != "bar" { 58 t.Errorf("until.Do returned non-nil error: %v", err) 59 } 60 atomic.AddUint64(&finishedCount, 1) 61 }() 62 } 63 time.Sleep(50 * time.Millisecond) 64 if c := atomic.LoadUint64(&finishedCount); c != goroutineCount { 65 t.Errorf("finished goroutines count: %v, want 0", c) 66 } 67 until.Close() 68 } 69 70 func TestUntil_DoBlockingAndGot(t *testing.T) { 71 var mu sync.Mutex 72 var fn = func() (any, error) { 73 return "bar", fmt.Errorf("must error") 74 } 75 76 var fnHolder = func() (any, error) { 77 mu.Lock() 78 defer mu.Unlock() 79 return fn() 80 } 81 82 var until sync_.Until 83 // All goroutines should block because picker is nil in until. 84 var finishedCount uint64 85 for i := goroutineCount; i > 0; i-- { 86 go func() { 87 if tr, err := until.Do(context.Background(), fnHolder); err != nil || tr != "bar" { 88 t.Errorf("until.Do returned non-nil error: %v", err) 89 } 90 atomic.AddUint64(&finishedCount, 1) 91 }() 92 } 93 time.Sleep(50 * time.Millisecond) 94 if c := atomic.LoadUint64(&finishedCount); c != 0 { 95 t.Errorf("finished goroutines count: %v, want 0", c) 96 } 97 fn = func() (any, error) { 98 return "bar", nil 99 } 100 until.Retry() 101 102 time.Sleep(50 * time.Millisecond) 103 if c := atomic.LoadUint64(&finishedCount); c != goroutineCount { 104 t.Errorf("finished goroutines count: %v, want 0", c) 105 } 106 until.Close() 107 }