github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/timeutil/timer_test.go (about)

     1  // Copyright 2016 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 timeutil
    12  
    13  import (
    14  	"fmt"
    15  	"testing"
    16  	"time"
    17  )
    18  
    19  const timeStep = 10 * time.Millisecond
    20  
    21  func TestTimerTimeout(t *testing.T) {
    22  	var timer Timer
    23  	defer func() {
    24  		if stopped := timer.Stop(); stopped {
    25  			t.Errorf("expected Stop to return false, got true")
    26  		}
    27  	}()
    28  	timer.Reset(timeStep)
    29  
    30  	<-timer.C
    31  	timer.Read = true
    32  
    33  	select {
    34  	case <-timer.C:
    35  		t.Errorf("expected timer to only timeout once after Reset; got two timeouts")
    36  	case <-time.After(5 * timeStep):
    37  	}
    38  }
    39  
    40  func TestTimerStop(t *testing.T) {
    41  	for sleepMult := time.Duration(0); sleepMult < 3; sleepMult++ {
    42  		sleepDur := sleepMult * timeStep
    43  		t.Run(fmt.Sprintf("sleepDur=%d*timeStep", sleepMult), func(t *testing.T) {
    44  			var timer Timer
    45  			timer.Reset(timeStep)
    46  			time.Sleep(sleepDur)
    47  
    48  			// Get a handle to the timer channel before calling Stop, because Stop
    49  			// clears the struct.
    50  			c := timer.C
    51  
    52  			// Even though we sleep for a certain duration which we know to be more
    53  			// or less than the timer's duration, we can't assert whether the timer
    54  			// fires before calling timer.Stop because we have no control over the
    55  			// scheduler. Instead, we handle both cases to avoid flakiness and assert
    56  			// that Stop returns the correct status.
    57  			stopped := timer.Stop()
    58  			select {
    59  			case <-c:
    60  				if stopped {
    61  					t.Errorf("timer unexpectedly fired after stopping")
    62  				}
    63  			case <-time.After(5 * timeStep):
    64  				if !stopped {
    65  					t.Errorf("timer did not fire after failing to stop")
    66  				}
    67  			}
    68  		})
    69  	}
    70  
    71  }
    72  
    73  func TestTimerUninitializedStopNoop(t *testing.T) {
    74  	var timer Timer
    75  	if stopped := timer.Stop(); stopped {
    76  		t.Errorf("expected Stop to return false when the timer was never reset, got true")
    77  	}
    78  }
    79  
    80  func TestTimerResetBeforeTimeout(t *testing.T) {
    81  	var timer Timer
    82  	defer timer.Stop()
    83  	timer.Reset(timeStep)
    84  
    85  	timer.Reset(timeStep)
    86  	<-timer.C
    87  	timer.Read = true
    88  
    89  	select {
    90  	case <-timer.C:
    91  		t.Errorf("expected timer to only timeout once after Reset; got two timeouts")
    92  	case <-time.After(5 * timeStep):
    93  	}
    94  }
    95  
    96  func TestTimerResetAfterTimeoutAndNoRead(t *testing.T) {
    97  	var timer Timer
    98  	defer timer.Stop()
    99  	timer.Reset(timeStep)
   100  
   101  	time.Sleep(2 * timeStep)
   102  
   103  	timer.Reset(timeStep)
   104  	<-timer.C
   105  	timer.Read = true
   106  
   107  	select {
   108  	case <-timer.C:
   109  		t.Errorf("expected timer to only timeout once after Reset; got two timeouts")
   110  	case <-time.After(5 * timeStep):
   111  	}
   112  }
   113  
   114  func TestTimerResetAfterTimeoutAndRead(t *testing.T) {
   115  	var timer Timer
   116  	defer timer.Stop()
   117  	timer.Reset(timeStep)
   118  
   119  	<-timer.C
   120  	timer.Read = true
   121  
   122  	timer.Reset(timeStep)
   123  	<-timer.C
   124  	timer.Read = true
   125  
   126  	select {
   127  	case <-timer.C:
   128  		t.Errorf("expected timer to only timeout once after Reset; got two timeouts")
   129  	case <-time.After(5 * timeStep):
   130  	}
   131  }
   132  
   133  func TestTimerMakesProgressInLoop(t *testing.T) {
   134  	var timer Timer
   135  	defer timer.Stop()
   136  	for i := 0; i < 5; i++ {
   137  		timer.Reset(timeStep)
   138  		<-timer.C
   139  		timer.Read = true
   140  	}
   141  }