k8s.io/client-go@v0.22.2/util/workqueue/delaying_queue_test.go (about)

     1  /*
     2  Copyright 2016 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 workqueue
    18  
    19  import (
    20  	"fmt"
    21  	"math/rand"
    22  	"reflect"
    23  	"testing"
    24  	"time"
    25  
    26  	"k8s.io/apimachinery/pkg/util/clock"
    27  	"k8s.io/apimachinery/pkg/util/wait"
    28  )
    29  
    30  func TestSimpleQueue(t *testing.T) {
    31  	fakeClock := clock.NewFakeClock(time.Now())
    32  	q := NewDelayingQueueWithCustomClock(fakeClock, "")
    33  
    34  	first := "foo"
    35  
    36  	q.AddAfter(first, 50*time.Millisecond)
    37  	if err := waitForWaitingQueueToFill(q); err != nil {
    38  		t.Fatalf("unexpected err: %v", err)
    39  	}
    40  
    41  	if q.Len() != 0 {
    42  		t.Errorf("should not have added")
    43  	}
    44  
    45  	fakeClock.Step(60 * time.Millisecond)
    46  
    47  	if err := waitForAdded(q, 1); err != nil {
    48  		t.Errorf("should have added")
    49  	}
    50  	item, _ := q.Get()
    51  	q.Done(item)
    52  
    53  	// step past the next heartbeat
    54  	fakeClock.Step(10 * time.Second)
    55  
    56  	err := wait.Poll(1*time.Millisecond, 30*time.Millisecond, func() (done bool, err error) {
    57  		if q.Len() > 0 {
    58  			return false, fmt.Errorf("added to queue")
    59  		}
    60  
    61  		return false, nil
    62  	})
    63  	if err != wait.ErrWaitTimeout {
    64  		t.Errorf("expected timeout, got: %v", err)
    65  	}
    66  
    67  	if q.Len() != 0 {
    68  		t.Errorf("should not have added")
    69  	}
    70  }
    71  
    72  func TestDeduping(t *testing.T) {
    73  	fakeClock := clock.NewFakeClock(time.Now())
    74  	q := NewDelayingQueueWithCustomClock(fakeClock, "")
    75  
    76  	first := "foo"
    77  
    78  	q.AddAfter(first, 50*time.Millisecond)
    79  	if err := waitForWaitingQueueToFill(q); err != nil {
    80  		t.Fatalf("unexpected err: %v", err)
    81  	}
    82  	q.AddAfter(first, 70*time.Millisecond)
    83  	if err := waitForWaitingQueueToFill(q); err != nil {
    84  		t.Fatalf("unexpected err: %v", err)
    85  	}
    86  	if q.Len() != 0 {
    87  		t.Errorf("should not have added")
    88  	}
    89  
    90  	// step past the first block, we should receive now
    91  	fakeClock.Step(60 * time.Millisecond)
    92  	if err := waitForAdded(q, 1); err != nil {
    93  		t.Errorf("should have added")
    94  	}
    95  	item, _ := q.Get()
    96  	q.Done(item)
    97  
    98  	// step past the second add
    99  	fakeClock.Step(20 * time.Millisecond)
   100  	if q.Len() != 0 {
   101  		t.Errorf("should not have added")
   102  	}
   103  
   104  	// test again, but this time the earlier should override
   105  	q.AddAfter(first, 50*time.Millisecond)
   106  	q.AddAfter(first, 30*time.Millisecond)
   107  	if err := waitForWaitingQueueToFill(q); err != nil {
   108  		t.Fatalf("unexpected err: %v", err)
   109  	}
   110  	if q.Len() != 0 {
   111  		t.Errorf("should not have added")
   112  	}
   113  
   114  	fakeClock.Step(40 * time.Millisecond)
   115  	if err := waitForAdded(q, 1); err != nil {
   116  		t.Errorf("should have added")
   117  	}
   118  	item, _ = q.Get()
   119  	q.Done(item)
   120  
   121  	// step past the second add
   122  	fakeClock.Step(20 * time.Millisecond)
   123  	if q.Len() != 0 {
   124  		t.Errorf("should not have added")
   125  	}
   126  	if q.Len() != 0 {
   127  		t.Errorf("should not have added")
   128  	}
   129  }
   130  
   131  func TestAddTwoFireEarly(t *testing.T) {
   132  	fakeClock := clock.NewFakeClock(time.Now())
   133  	q := NewDelayingQueueWithCustomClock(fakeClock, "")
   134  
   135  	first := "foo"
   136  	second := "bar"
   137  	third := "baz"
   138  
   139  	q.AddAfter(first, 1*time.Second)
   140  	q.AddAfter(second, 50*time.Millisecond)
   141  	if err := waitForWaitingQueueToFill(q); err != nil {
   142  		t.Fatalf("unexpected err: %v", err)
   143  	}
   144  
   145  	if q.Len() != 0 {
   146  		t.Errorf("should not have added")
   147  	}
   148  
   149  	fakeClock.Step(60 * time.Millisecond)
   150  
   151  	if err := waitForAdded(q, 1); err != nil {
   152  		t.Fatalf("unexpected err: %v", err)
   153  	}
   154  	item, _ := q.Get()
   155  	if !reflect.DeepEqual(item, second) {
   156  		t.Errorf("expected %v, got %v", second, item)
   157  	}
   158  
   159  	q.AddAfter(third, 2*time.Second)
   160  
   161  	fakeClock.Step(1 * time.Second)
   162  	if err := waitForAdded(q, 1); err != nil {
   163  		t.Fatalf("unexpected err: %v", err)
   164  	}
   165  	item, _ = q.Get()
   166  	if !reflect.DeepEqual(item, first) {
   167  		t.Errorf("expected %v, got %v", first, item)
   168  	}
   169  
   170  	fakeClock.Step(2 * time.Second)
   171  	if err := waitForAdded(q, 1); err != nil {
   172  		t.Fatalf("unexpected err: %v", err)
   173  	}
   174  	item, _ = q.Get()
   175  	if !reflect.DeepEqual(item, third) {
   176  		t.Errorf("expected %v, got %v", third, item)
   177  	}
   178  }
   179  
   180  func TestCopyShifting(t *testing.T) {
   181  	fakeClock := clock.NewFakeClock(time.Now())
   182  	q := NewDelayingQueueWithCustomClock(fakeClock, "")
   183  
   184  	first := "foo"
   185  	second := "bar"
   186  	third := "baz"
   187  
   188  	q.AddAfter(first, 1*time.Second)
   189  	q.AddAfter(second, 500*time.Millisecond)
   190  	q.AddAfter(third, 250*time.Millisecond)
   191  	if err := waitForWaitingQueueToFill(q); err != nil {
   192  		t.Fatalf("unexpected err: %v", err)
   193  	}
   194  
   195  	if q.Len() != 0 {
   196  		t.Errorf("should not have added")
   197  	}
   198  
   199  	fakeClock.Step(2 * time.Second)
   200  
   201  	if err := waitForAdded(q, 3); err != nil {
   202  		t.Fatalf("unexpected err: %v", err)
   203  	}
   204  	actualFirst, _ := q.Get()
   205  	if !reflect.DeepEqual(actualFirst, third) {
   206  		t.Errorf("expected %v, got %v", third, actualFirst)
   207  	}
   208  	actualSecond, _ := q.Get()
   209  	if !reflect.DeepEqual(actualSecond, second) {
   210  		t.Errorf("expected %v, got %v", second, actualSecond)
   211  	}
   212  	actualThird, _ := q.Get()
   213  	if !reflect.DeepEqual(actualThird, first) {
   214  		t.Errorf("expected %v, got %v", first, actualThird)
   215  	}
   216  }
   217  
   218  func BenchmarkDelayingQueue_AddAfter(b *testing.B) {
   219  	fakeClock := clock.NewFakeClock(time.Now())
   220  	q := NewDelayingQueueWithCustomClock(fakeClock, "")
   221  
   222  	// Add items
   223  	for n := 0; n < b.N; n++ {
   224  		data := fmt.Sprintf("%d", n)
   225  		q.AddAfter(data, time.Duration(rand.Int63n(int64(10*time.Minute))))
   226  	}
   227  
   228  	// Exercise item removal as well
   229  	fakeClock.Step(11 * time.Minute)
   230  	for n := 0; n < b.N; n++ {
   231  		_, _ = q.Get()
   232  	}
   233  }
   234  
   235  func waitForAdded(q DelayingInterface, depth int) error {
   236  	return wait.Poll(1*time.Millisecond, 10*time.Second, func() (done bool, err error) {
   237  		if q.Len() == depth {
   238  			return true, nil
   239  		}
   240  
   241  		return false, nil
   242  	})
   243  }
   244  
   245  func waitForWaitingQueueToFill(q DelayingInterface) error {
   246  	return wait.Poll(1*time.Millisecond, 10*time.Second, func() (done bool, err error) {
   247  		if len(q.(*delayingType).waitingForAddCh) == 0 {
   248  			return true, nil
   249  		}
   250  
   251  		return false, nil
   252  	})
   253  }