github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/cmn/tests/sync_test.go (about) 1 // Package test provides tests for common low-level types and utilities for all aistore projects 2 /* 3 * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package tests_test 6 7 import ( 8 "sync" 9 "testing" 10 "time" 11 12 "github.com/NVIDIA/aistore/cmn/atomic" 13 "github.com/NVIDIA/aistore/cmn/cos" 14 "github.com/NVIDIA/aistore/tools" 15 ) 16 17 func TestTimeoutGroupSmoke(t *testing.T) { 18 tools.CheckSkip(t, &tools.SkipTestArgs{Long: true}) 19 wg := cos.NewTimeoutGroup() 20 wg.Add(1) 21 wg.Done() 22 if wg.WaitTimeout(time.Second) { 23 t.Error("wait timed out") 24 } 25 } 26 27 func TestTimeoutGroupWait(t *testing.T) { 28 tools.CheckSkip(t, &tools.SkipTestArgs{Long: true}) 29 wg := cos.NewTimeoutGroup() 30 wg.Add(2) 31 wg.Done() 32 wg.Done() 33 wg.Wait() 34 } 35 36 func TestTimeoutGroupGoroutines(t *testing.T) { 37 tools.CheckSkip(t, &tools.SkipTestArgs{Long: true}) 38 wg := cos.NewTimeoutGroup() 39 40 for range 100000 { 41 wg.Add(1) 42 go func() { 43 time.Sleep(time.Second * 2) 44 wg.Done() 45 }() 46 } 47 48 if wg.WaitTimeout(time.Second * 5) { 49 t.Error("wait timed out") 50 } 51 } 52 53 func TestTimeoutGroupTimeout(t *testing.T) { 54 tools.CheckSkip(t, &tools.SkipTestArgs{Long: true}) 55 wg := cos.NewTimeoutGroup() 56 wg.Add(1) 57 58 go func() { 59 time.Sleep(time.Second * 3) 60 wg.Done() 61 }() 62 63 if !wg.WaitTimeout(time.Second) { 64 t.Error("group did not time out") 65 } 66 67 if wg.WaitTimeout(time.Second * 3) { // now wait for actual end of the job 68 t.Error("group timed out") 69 } 70 } 71 72 func TestTimeoutGroupStop(t *testing.T) { 73 tools.CheckSkip(t, &tools.SkipTestArgs{Long: true}) 74 wg := cos.NewTimeoutGroup() 75 wg.Add(1) 76 77 go func() { 78 time.Sleep(time.Second * 3) 79 wg.Done() 80 }() 81 82 if !wg.WaitTimeout(time.Second) { 83 t.Error("group did not time out") 84 } 85 86 stopCh := make(chan struct{}, 1) 87 stopCh <- struct{}{} 88 89 timed, stopped := wg.WaitTimeoutWithStop(time.Second, stopCh) 90 if timed { 91 t.Error("group should not time out") 92 } 93 94 if !stopped { 95 t.Error("group should be stopped") 96 } 97 98 if timed, stopped = wg.WaitTimeoutWithStop(time.Second*3, stopCh); timed || stopped { 99 t.Error("group timed out or was stopped on finish") 100 } 101 } 102 103 func TestTimeoutGroupStopAndTimeout(t *testing.T) { 104 tools.CheckSkip(t, &tools.SkipTestArgs{Long: true}) 105 wg := cos.NewTimeoutGroup() 106 wg.Add(1) 107 108 go func() { 109 time.Sleep(time.Second * 3) 110 wg.Done() 111 }() 112 113 stopCh := make(chan struct{}, 1) 114 timed, stopped := wg.WaitTimeoutWithStop(time.Second, stopCh) 115 if !timed { 116 t.Error("group should time out") 117 } 118 119 if stopped { 120 t.Error("group should not be stopped") 121 } 122 123 if timed, stopped = wg.WaitTimeoutWithStop(time.Second*3, stopCh); timed || stopped { 124 t.Error("group timed out or was stopped on finish") 125 } 126 } 127 128 func TestSemaphore(t *testing.T) { 129 tools.CheckSkip(t, &tools.SkipTestArgs{Long: true}) 130 sema := cos.NewSemaphore(2) 131 sema.Acquire() 132 sema.Acquire() 133 134 select { 135 case <-sema.TryAcquire(): 136 t.Error("unexpected acquire") 137 default: 138 break 139 } 140 141 sema.Release() 142 143 select { 144 case <-sema.TryAcquire(): 145 default: 146 t.Error("expected acquire to happen") 147 } 148 } 149 150 func TestDynSemaphore(t *testing.T) { 151 tools.CheckSkip(t, &tools.SkipTestArgs{Long: true}) 152 limit := 10 153 154 sema := cos.NewDynSemaphore(limit) 155 156 var i atomic.Int32 157 wg := &sync.WaitGroup{} 158 ch := make(chan int32, 10*limit) 159 160 for range 10 * limit { 161 sema.Acquire() 162 wg.Add(1) 163 go func() { 164 ch <- i.Inc() 165 time.Sleep(time.Millisecond) 166 i.Dec() 167 sema.Release() 168 wg.Done() 169 }() 170 } 171 172 wg.Wait() 173 close(ch) 174 175 res := int32(0) 176 for c := range ch { 177 res = max(res, c) 178 } 179 180 if int(res) != limit { 181 t.Fatalf("acutal limit %d was different than expected %d", res, limit) 182 } 183 }