diff options
Diffstat (limited to 'pkg/tcpip/timer_test.go')
-rw-r--r-- | pkg/tcpip/timer_test.go | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/pkg/tcpip/timer_test.go b/pkg/tcpip/timer_test.go index 2d20f7ef3..b4940e397 100644 --- a/pkg/tcpip/timer_test.go +++ b/pkg/tcpip/timer_test.go @@ -28,13 +28,38 @@ const ( longDuration = 1 * time.Second ) +func TestCancellableTimerReassignment(t *testing.T) { + var timer tcpip.CancellableTimer + var wg sync.WaitGroup + var lock sync.Mutex + + for i := 0; i < 2; i++ { + wg.Add(1) + + go func() { + lock.Lock() + // Assigning a new timer value updates the timer's locker and function. + // This test makes sure there is no data race when reassigning a timer + // that has an active timer (even if it has been stopped as a stopped + // timer may be blocked on a lock before it can check if it has been + // stopped while another goroutine holds the same lock). + timer = *tcpip.NewCancellableTimer(&lock, func() { + wg.Done() + }) + timer.Reset(shortDuration) + lock.Unlock() + }() + } + wg.Wait() +} + func TestCancellableTimerFire(t *testing.T) { t.Parallel() ch := make(chan struct{}) var lock sync.Mutex - timer := tcpip.MakeCancellableTimer(&lock, func() { + timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} }) timer.Reset(shortDuration) @@ -60,7 +85,7 @@ func TestCancellableTimerResetFromLongDuration(t *testing.T) { ch := make(chan struct{}) var lock sync.Mutex - timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} }) + timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} }) timer.Reset(middleDuration) lock.Lock() @@ -91,7 +116,7 @@ func TestCancellableTimerResetFromShortDuration(t *testing.T) { var lock sync.Mutex lock.Lock() - timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} }) + timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} }) timer.Reset(shortDuration) timer.StopLocked() lock.Unlock() @@ -128,7 +153,7 @@ func TestCancellableTimerImmediatelyStop(t *testing.T) { for i := 0; i < 1000; i++ { lock.Lock() - timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} }) + timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} }) timer.Reset(shortDuration) timer.StopLocked() lock.Unlock() @@ -149,7 +174,7 @@ func TestCancellableTimerStoppedResetWithoutLock(t *testing.T) { var lock sync.Mutex lock.Lock() - timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} }) + timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} }) timer.Reset(shortDuration) timer.StopLocked() lock.Unlock() @@ -180,7 +205,7 @@ func TestManyCancellableTimerResetAfterBlockedOnLock(t *testing.T) { var lock sync.Mutex lock.Lock() - timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} }) + timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} }) timer.Reset(shortDuration) for i := 0; i < 10; i++ { // Sleep until the timer fires and gets blocked trying to take the lock. @@ -212,7 +237,7 @@ func TestManyCancellableTimerResetUnderLock(t *testing.T) { var lock sync.Mutex lock.Lock() - timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} }) + timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} }) timer.Reset(shortDuration) for i := 0; i < 10; i++ { timer.StopLocked() |