...

Source file src/k8s.io/utils/clock/testing/fake_clock_test.go

Documentation: k8s.io/utils/clock/testing

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package testing
    18  
    19  import (
    20  	"testing"
    21  	"time"
    22  
    23  	"k8s.io/utils/clock"
    24  )
    25  
    26  type SettablePassiveClock interface {
    27  	clock.PassiveClock
    28  	SetTime(time.Time)
    29  }
    30  
    31  func exercisePassiveClock(t *testing.T, pc SettablePassiveClock) {
    32  	t1 := time.Now()
    33  	t2 := t1.Add(time.Hour)
    34  	pc.SetTime(t1)
    35  	tx := pc.Now()
    36  	if tx != t1 {
    37  		t.Errorf("SetTime(%#+v); Now() => %#+v", t1, tx)
    38  	}
    39  	dx := pc.Since(t1)
    40  	if dx != 0 {
    41  		t.Errorf("Since() => %v", dx)
    42  	}
    43  	pc.SetTime(t2)
    44  	dx = pc.Since(t1)
    45  	if dx != time.Hour {
    46  		t.Errorf("Since() => %v", dx)
    47  	}
    48  	tx = pc.Now()
    49  	if tx != t2 {
    50  		t.Errorf("Now() => %#+v", tx)
    51  	}
    52  }
    53  
    54  func TestFakePassiveClock(t *testing.T) {
    55  	startTime := time.Now()
    56  	tc := NewFakePassiveClock(startTime)
    57  	exercisePassiveClock(t, tc)
    58  }
    59  
    60  func TestFakeClock(t *testing.T) {
    61  	startTime := time.Now()
    62  	tc := NewFakeClock(startTime)
    63  	exercisePassiveClock(t, tc)
    64  	tc.SetTime(startTime)
    65  	tc.Step(time.Second)
    66  	now := tc.Now()
    67  	if now.Sub(startTime) != time.Second {
    68  		t.Errorf("input: %s now=%s gap=%s expected=%s", startTime, now, now.Sub(startTime), time.Second)
    69  	}
    70  }
    71  
    72  func TestFakeClockSleep(t *testing.T) {
    73  	startTime := time.Now()
    74  	tc := NewFakeClock(startTime)
    75  	tc.Sleep(time.Duration(1) * time.Hour)
    76  	now := tc.Now()
    77  	if now.Sub(startTime) != time.Hour {
    78  		t.Errorf("Fake sleep failed, expected time to advance by one hour, instead, its %v", now.Sub(startTime))
    79  	}
    80  }
    81  
    82  func TestFakeAfter(t *testing.T) {
    83  	tc := NewFakeClock(time.Now())
    84  	if tc.HasWaiters() {
    85  		t.Errorf("unexpected waiter?")
    86  	}
    87  	oneSec := tc.After(time.Second)
    88  	if !tc.HasWaiters() {
    89  		t.Errorf("unexpected lack of waiter?")
    90  	}
    91  
    92  	oneOhOneSec := tc.After(time.Second + time.Millisecond)
    93  	twoSec := tc.After(2 * time.Second)
    94  	select {
    95  	case <-oneSec:
    96  		t.Errorf("unexpected channel read")
    97  	case <-oneOhOneSec:
    98  		t.Errorf("unexpected channel read")
    99  	case <-twoSec:
   100  		t.Errorf("unexpected channel read")
   101  	default:
   102  	}
   103  
   104  	tc.Step(999 * time.Millisecond)
   105  	select {
   106  	case <-oneSec:
   107  		t.Errorf("unexpected channel read")
   108  	case <-oneOhOneSec:
   109  		t.Errorf("unexpected channel read")
   110  	case <-twoSec:
   111  		t.Errorf("unexpected channel read")
   112  	default:
   113  	}
   114  
   115  	tc.Step(time.Millisecond)
   116  	select {
   117  	case <-oneSec:
   118  		// Expected!
   119  	case <-oneOhOneSec:
   120  		t.Errorf("unexpected channel read")
   121  	case <-twoSec:
   122  		t.Errorf("unexpected channel read")
   123  	default:
   124  		t.Errorf("unexpected non-channel read")
   125  	}
   126  	tc.Step(time.Millisecond)
   127  	select {
   128  	case <-oneSec:
   129  		// should not double-trigger!
   130  		t.Errorf("unexpected channel read")
   131  	case <-oneOhOneSec:
   132  		// Expected!
   133  	case <-twoSec:
   134  		t.Errorf("unexpected channel read")
   135  	default:
   136  		t.Errorf("unexpected non-channel read")
   137  	}
   138  }
   139  
   140  func TestFakeAfterFunc(t *testing.T) {
   141  	tc := NewFakeClock(time.Now())
   142  	if tc.HasWaiters() {
   143  		t.Errorf("unexpected waiter?")
   144  	}
   145  	expectOneSecTimerFire := false
   146  	oneSecTimerFire := 0
   147  	tc.AfterFunc(time.Second, func() {
   148  		if !expectOneSecTimerFire {
   149  			t.Errorf("oneSecTimer func fired")
   150  		} else {
   151  			oneSecTimerFire++
   152  		}
   153  	})
   154  	if !tc.HasWaiters() {
   155  		t.Errorf("unexpected lack of waiter?")
   156  	}
   157  
   158  	expectOneOhOneSecTimerFire := false
   159  	oneOhOneSecTimerFire := 0
   160  	tc.AfterFunc(time.Second+time.Millisecond, func() {
   161  		if !expectOneOhOneSecTimerFire {
   162  			t.Errorf("oneOhOneSecTimer func fired")
   163  		} else {
   164  			oneOhOneSecTimerFire++
   165  		}
   166  	})
   167  
   168  	expectTwoSecTimerFire := false
   169  	twoSecTimerFire := 0
   170  	twoSecTimer := tc.AfterFunc(2*time.Second, func() {
   171  		if !expectTwoSecTimerFire {
   172  			t.Errorf("twoSecTimer func fired")
   173  		} else {
   174  			twoSecTimerFire++
   175  		}
   176  	})
   177  
   178  	tc.Step(999 * time.Millisecond)
   179  
   180  	expectOneSecTimerFire = true
   181  	tc.Step(time.Millisecond)
   182  	if oneSecTimerFire != 1 {
   183  		t.Errorf("expected oneSecTimerFire=1, got %d", oneSecTimerFire)
   184  	}
   185  	expectOneSecTimerFire = false
   186  
   187  	expectOneOhOneSecTimerFire = true
   188  	tc.Step(time.Millisecond)
   189  	if oneOhOneSecTimerFire != 1 {
   190  		// should not double-trigger!
   191  		t.Errorf("expected oneOhOneSecTimerFire=1, got %d", oneOhOneSecTimerFire)
   192  	}
   193  	expectOneOhOneSecTimerFire = false
   194  
   195  	// ensure a canceled timer doesn't fire
   196  	twoSecTimer.Stop()
   197  	tc.Step(time.Second)
   198  }
   199  
   200  func TestFakeTick(t *testing.T) {
   201  	tc := NewFakeClock(time.Now())
   202  	if tc.HasWaiters() {
   203  		t.Errorf("unexpected waiter?")
   204  	}
   205  	oneSec := tc.Tick(time.Second)
   206  	if !tc.HasWaiters() {
   207  		t.Errorf("unexpected lack of waiter?")
   208  	}
   209  
   210  	oneOhOneSec := tc.Tick(time.Second + time.Millisecond)
   211  	twoSec := tc.Tick(2 * time.Second)
   212  	select {
   213  	case <-oneSec:
   214  		t.Errorf("unexpected channel read")
   215  	case <-oneOhOneSec:
   216  		t.Errorf("unexpected channel read")
   217  	case <-twoSec:
   218  		t.Errorf("unexpected channel read")
   219  	default:
   220  	}
   221  
   222  	tc.Step(999 * time.Millisecond) // t=.999
   223  	select {
   224  	case <-oneSec:
   225  		t.Errorf("unexpected channel read")
   226  	case <-oneOhOneSec:
   227  		t.Errorf("unexpected channel read")
   228  	case <-twoSec:
   229  		t.Errorf("unexpected channel read")
   230  	default:
   231  	}
   232  
   233  	tc.Step(time.Millisecond) // t=1.000
   234  	select {
   235  	case <-oneSec:
   236  		// Expected!
   237  	case <-oneOhOneSec:
   238  		t.Errorf("unexpected channel read")
   239  	case <-twoSec:
   240  		t.Errorf("unexpected channel read")
   241  	default:
   242  		t.Errorf("unexpected non-channel read")
   243  	}
   244  	tc.Step(time.Millisecond) // t=1.001
   245  	select {
   246  	case <-oneSec:
   247  		// should not double-trigger!
   248  		t.Errorf("unexpected channel read")
   249  	case <-oneOhOneSec:
   250  		// Expected!
   251  	case <-twoSec:
   252  		t.Errorf("unexpected channel read")
   253  	default:
   254  		t.Errorf("unexpected non-channel read")
   255  	}
   256  
   257  	tc.Step(time.Second) // t=2.001
   258  	tc.Step(time.Second) // t=3.001
   259  	tc.Step(time.Second) // t=4.001
   260  	tc.Step(time.Second) // t=5.001
   261  
   262  	// The one second ticker should not accumulate ticks
   263  	accumulatedTicks := 0
   264  	drained := false
   265  	for !drained {
   266  		select {
   267  		case <-oneSec:
   268  			accumulatedTicks++
   269  		default:
   270  			drained = true
   271  		}
   272  	}
   273  	if accumulatedTicks != 1 {
   274  		t.Errorf("unexpected number of accumulated ticks: %d", accumulatedTicks)
   275  	}
   276  }
   277  
   278  func TestFakeStop(t *testing.T) {
   279  	tc := NewFakeClock(time.Now())
   280  	timer := tc.NewTimer(time.Second)
   281  	if !tc.HasWaiters() {
   282  		t.Errorf("expected a waiter to be present, but it is not")
   283  	}
   284  	timer.Stop()
   285  	if tc.HasWaiters() {
   286  		t.Errorf("expected existing waiter to be cleaned up, but it is still present")
   287  	}
   288  }
   289  
   290  // This tests the pattern documented in the go docs here: https://golang.org/pkg/time/#Timer.Stop
   291  // This pattern is required to safely reset a timer, so should be common.
   292  // This also tests resetting the timer
   293  func TestFakeStopDrain(t *testing.T) {
   294  	start := time.Time{}
   295  	tc := NewFakeClock(start)
   296  	timer := tc.NewTimer(time.Second)
   297  	tc.Step(1 * time.Second)
   298  	// Effectively `if !timer.Stop { <-t.C }` but with more asserts
   299  	if timer.Stop() {
   300  		t.Errorf("stop should report the timer had triggered")
   301  	}
   302  	if readTime := assertReadTime(t, timer.C()); !readTime.Equal(start.Add(1 * time.Second)) {
   303  		t.Errorf("timer should have ticked after 1 second, got %v", readTime)
   304  	}
   305  
   306  	timer.Reset(time.Second)
   307  	if !tc.HasWaiters() {
   308  		t.Errorf("expected a waiter to be present, but it is not")
   309  	}
   310  	select {
   311  	case <-timer.C():
   312  		t.Fatal("got time early on clock; haven't stepped yet")
   313  	default:
   314  	}
   315  	tc.Step(1 * time.Second)
   316  	if readTime := assertReadTime(t, timer.C()); !readTime.Equal(start.Add(2 * time.Second)) {
   317  		t.Errorf("timer should have ticked again after reset + 1 more second, got %v", readTime)
   318  	}
   319  }
   320  
   321  func TestTimerNegative(t *testing.T) {
   322  	tc := NewFakeClock(time.Now())
   323  	timer := tc.NewTimer(-1 * time.Second)
   324  	if !tc.HasWaiters() {
   325  		t.Errorf("expected a waiter to be present, but it is not")
   326  	}
   327  	// force waiters to be called
   328  	tc.Step(0)
   329  	tick := assertReadTime(t, timer.C())
   330  	if tick != tc.Now() {
   331  		t.Errorf("expected -1s to turn into now: %v != %v", tick, tc.Now())
   332  	}
   333  }
   334  
   335  func TestTickNegative(t *testing.T) {
   336  	// The stdlib 'Tick' returns nil for negative and zero values, so our fake
   337  	// should too.
   338  	tc := NewFakeClock(time.Now())
   339  	if tick := tc.Tick(-1 * time.Second); tick != nil {
   340  		t.Errorf("expected negative tick to be nil: %v", tick)
   341  	}
   342  	if tick := tc.Tick(0); tick != nil {
   343  		t.Errorf("expected negative tick to be nil: %v", tick)
   344  	}
   345  }
   346  
   347  // assertReadTime asserts that the channel can be read and returns the time it
   348  // reads from the channel.
   349  func assertReadTime(t testing.TB, c <-chan time.Time) time.Time {
   350  	type helper interface {
   351  		Helper()
   352  	}
   353  	if h, ok := t.(helper); ok {
   354  		h.Helper()
   355  	}
   356  	select {
   357  	case ti, ok := <-c:
   358  		if !ok {
   359  			t.Fatalf("expected to read time from channel, but it was closed")
   360  		}
   361  		return ti
   362  	default:
   363  		t.Fatalf("expected to read time from channel, but couldn't")
   364  	}
   365  	panic("unreachable")
   366  }
   367  

View as plain text