github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/sleep/sleep_test.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package sleep
    16  
    17  import (
    18  	"math/rand"
    19  	"runtime"
    20  	"testing"
    21  	"time"
    22  )
    23  
    24  // ZeroWakerNotAsserted tests that a zero-value waker is in non-asserted state.
    25  func ZeroWakerNotAsserted(t *testing.T) {
    26  	var w Waker
    27  	if w.IsAsserted() {
    28  		t.Fatalf("Zero waker is asserted")
    29  	}
    30  
    31  	if w.Clear() {
    32  		t.Fatalf("Zero waker is asserted")
    33  	}
    34  }
    35  
    36  // AssertedWakerAfterAssert tests that a waker properly reports its state as
    37  // asserted once its Assert() method is called.
    38  func AssertedWakerAfterAssert(t *testing.T) {
    39  	var w Waker
    40  	w.Assert()
    41  	if !w.IsAsserted() {
    42  		t.Fatalf("Asserted waker is not reported as such")
    43  	}
    44  
    45  	if !w.Clear() {
    46  		t.Fatalf("Asserted waker is not reported as such")
    47  	}
    48  }
    49  
    50  // AssertedWakerAfterTwoAsserts tests that a waker properly reports its state as
    51  // asserted once its Assert() method is called twice.
    52  func AssertedWakerAfterTwoAsserts(t *testing.T) {
    53  	var w Waker
    54  	w.Assert()
    55  	w.Assert()
    56  	if !w.IsAsserted() {
    57  		t.Fatalf("Asserted waker is not reported as such")
    58  	}
    59  
    60  	if !w.Clear() {
    61  		t.Fatalf("Asserted waker is not reported as such")
    62  	}
    63  }
    64  
    65  // NotAssertedWakerWithSleeper tests that a waker properly reports its state as
    66  // not asserted after a sleeper is associated with it.
    67  func NotAssertedWakerWithSleeper(t *testing.T) {
    68  	var w Waker
    69  	var s Sleeper
    70  	s.AddWaker(&w, 0)
    71  	if w.IsAsserted() {
    72  		t.Fatalf("Non-asserted waker is reported as asserted")
    73  	}
    74  
    75  	if w.Clear() {
    76  		t.Fatalf("Non-asserted waker is reported as asserted")
    77  	}
    78  }
    79  
    80  // NotAssertedWakerAfterWake tests that a waker properly reports its state as
    81  // not asserted after a previous assert is consumed by a sleeper. That is, tests
    82  // the "edge-triggered" behavior.
    83  func NotAssertedWakerAfterWake(t *testing.T) {
    84  	var w Waker
    85  	var s Sleeper
    86  	s.AddWaker(&w, 0)
    87  	w.Assert()
    88  	s.Fetch(true)
    89  	if w.IsAsserted() {
    90  		t.Fatalf("Consumed waker is reported as asserted")
    91  	}
    92  
    93  	if w.Clear() {
    94  		t.Fatalf("Consumed waker is reported as asserted")
    95  	}
    96  }
    97  
    98  // AssertedWakerBeforeAdd tests that a waker causes a sleeper to not sleep if
    99  // it's already asserted before being added.
   100  func AssertedWakerBeforeAdd(t *testing.T) {
   101  	var w Waker
   102  	var s Sleeper
   103  	w.Assert()
   104  	s.AddWaker(&w, 0)
   105  
   106  	if _, ok := s.Fetch(false); !ok {
   107  		t.Fatalf("Fetch failed even though asserted waker was added")
   108  	}
   109  }
   110  
   111  // ClearedWaker tests that a waker properly reports its state as not asserted
   112  // after it is cleared.
   113  func ClearedWaker(t *testing.T) {
   114  	var w Waker
   115  	w.Assert()
   116  	w.Clear()
   117  	if w.IsAsserted() {
   118  		t.Fatalf("Cleared waker is reported as asserted")
   119  	}
   120  
   121  	if w.Clear() {
   122  		t.Fatalf("Cleared waker is reported as asserted")
   123  	}
   124  }
   125  
   126  // ClearedWakerWithSleeper tests that a waker properly reports its state as
   127  // not asserted when it is cleared while it has a sleeper associated with it.
   128  func ClearedWakerWithSleeper(t *testing.T) {
   129  	var w Waker
   130  	var s Sleeper
   131  	s.AddWaker(&w, 0)
   132  	w.Clear()
   133  	if w.IsAsserted() {
   134  		t.Fatalf("Cleared waker is reported as asserted")
   135  	}
   136  
   137  	if w.Clear() {
   138  		t.Fatalf("Cleared waker is reported as asserted")
   139  	}
   140  }
   141  
   142  // ClearedWakerAssertedWithSleeper tests that a waker properly reports its state
   143  // as not asserted when it is cleared while it has a sleeper associated with it
   144  // and has been asserted.
   145  func ClearedWakerAssertedWithSleeper(t *testing.T) {
   146  	var w Waker
   147  	var s Sleeper
   148  	s.AddWaker(&w, 0)
   149  	w.Assert()
   150  	w.Clear()
   151  	if w.IsAsserted() {
   152  		t.Fatalf("Cleared waker is reported as asserted")
   153  	}
   154  
   155  	if w.Clear() {
   156  		t.Fatalf("Cleared waker is reported as asserted")
   157  	}
   158  }
   159  
   160  // TestBlock tests that a sleeper actually blocks waiting for the waker to
   161  // assert its state.
   162  func TestBlock(t *testing.T) {
   163  	var w Waker
   164  	var s Sleeper
   165  
   166  	s.AddWaker(&w, 0)
   167  
   168  	// Assert waker after one second.
   169  	before := time.Now()
   170  	go func() {
   171  		time.Sleep(1 * time.Second)
   172  		w.Assert()
   173  	}()
   174  
   175  	// Fetch the result and make sure it took at least 500ms.
   176  	if _, ok := s.Fetch(true); !ok {
   177  		t.Fatalf("Fetch failed unexpectedly")
   178  	}
   179  	if d := time.Now().Sub(before); d < 500*time.Millisecond {
   180  		t.Fatalf("Duration was too short: %v", d)
   181  	}
   182  
   183  	// Check that already-asserted waker completes inline.
   184  	w.Assert()
   185  	if _, ok := s.Fetch(true); !ok {
   186  		t.Fatalf("Fetch failed unexpectedly")
   187  	}
   188  
   189  	// Check that fetch sleeps if waker had been asserted but was reset
   190  	// before Fetch is called.
   191  	w.Assert()
   192  	w.Clear()
   193  	before = time.Now()
   194  	go func() {
   195  		time.Sleep(1 * time.Second)
   196  		w.Assert()
   197  	}()
   198  	if _, ok := s.Fetch(true); !ok {
   199  		t.Fatalf("Fetch failed unexpectedly")
   200  	}
   201  	if d := time.Now().Sub(before); d < 500*time.Millisecond {
   202  		t.Fatalf("Duration was too short: %v", d)
   203  	}
   204  }
   205  
   206  // TestNonBlock checks that a sleeper won't block if waker isn't asserted.
   207  func TestNonBlock(t *testing.T) {
   208  	var w Waker
   209  	var s Sleeper
   210  
   211  	// Don't block when there's no waker.
   212  	if _, ok := s.Fetch(false); ok {
   213  		t.Fatalf("Fetch succeeded when there is no waker")
   214  	}
   215  
   216  	// Don't block when waker isn't asserted.
   217  	s.AddWaker(&w, 0)
   218  	if _, ok := s.Fetch(false); ok {
   219  		t.Fatalf("Fetch succeeded when waker was not asserted")
   220  	}
   221  
   222  	// Don't block when waker was asserted, but isn't anymore.
   223  	w.Assert()
   224  	w.Clear()
   225  	if _, ok := s.Fetch(false); ok {
   226  		t.Fatalf("Fetch succeeded when waker was not asserted anymore")
   227  	}
   228  
   229  	// Don't block when waker was consumed by previous Fetch().
   230  	w.Assert()
   231  	if _, ok := s.Fetch(false); !ok {
   232  		t.Fatalf("Fetch failed even though waker was asserted")
   233  	}
   234  
   235  	if _, ok := s.Fetch(false); ok {
   236  		t.Fatalf("Fetch succeeded when waker had been consumed")
   237  	}
   238  }
   239  
   240  // TestMultiple checks that a sleeper can wait for and receives notifications
   241  // from multiple wakers.
   242  func TestMultiple(t *testing.T) {
   243  	s := Sleeper{}
   244  	w1 := Waker{}
   245  	w2 := Waker{}
   246  
   247  	s.AddWaker(&w1, 0)
   248  	s.AddWaker(&w2, 1)
   249  
   250  	w1.Assert()
   251  	w2.Assert()
   252  
   253  	v, ok := s.Fetch(false)
   254  	if !ok {
   255  		t.Fatalf("Fetch failed when there are asserted wakers")
   256  	}
   257  
   258  	if v != 0 && v != 1 {
   259  		t.Fatalf("Unexpected waker id: %v", v)
   260  	}
   261  
   262  	want := 1 - v
   263  	v, ok = s.Fetch(false)
   264  	if !ok {
   265  		t.Fatalf("Fetch failed when there is an asserted waker")
   266  	}
   267  
   268  	if v != want {
   269  		t.Fatalf("Unexpected waker id, got %v, want %v", v, want)
   270  	}
   271  }
   272  
   273  // TestDoneFunction tests if calling Done() on a sleeper works properly.
   274  func TestDoneFunction(t *testing.T) {
   275  	// Trivial case of no waker.
   276  	s := Sleeper{}
   277  	s.Done()
   278  
   279  	// Cases when the sleeper has n wakers, but none are asserted.
   280  	for n := 1; n < 20; n++ {
   281  		s := Sleeper{}
   282  		w := make([]Waker, n)
   283  		for j := 0; j < n; j++ {
   284  			s.AddWaker(&w[j], j)
   285  		}
   286  		s.Done()
   287  	}
   288  
   289  	// Cases when the sleeper has n wakers, and only the i-th one is
   290  	// asserted.
   291  	for n := 1; n < 20; n++ {
   292  		for i := 0; i < n; i++ {
   293  			s := Sleeper{}
   294  			w := make([]Waker, n)
   295  			for j := 0; j < n; j++ {
   296  				s.AddWaker(&w[j], j)
   297  			}
   298  			w[i].Assert()
   299  			s.Done()
   300  		}
   301  	}
   302  
   303  	// Cases when the sleeper has n wakers, and the i-th one is asserted
   304  	// and cleared.
   305  	for n := 1; n < 20; n++ {
   306  		for i := 0; i < n; i++ {
   307  			s := Sleeper{}
   308  			w := make([]Waker, n)
   309  			for j := 0; j < n; j++ {
   310  				s.AddWaker(&w[j], j)
   311  			}
   312  			w[i].Assert()
   313  			w[i].Clear()
   314  			s.Done()
   315  		}
   316  	}
   317  
   318  	// Cases when the sleeper has n wakers, with a random number of them
   319  	// asserted.
   320  	for n := 1; n < 20; n++ {
   321  		for iters := 0; iters < 1000; iters++ {
   322  			s := Sleeper{}
   323  			w := make([]Waker, n)
   324  			for j := 0; j < n; j++ {
   325  				s.AddWaker(&w[j], j)
   326  			}
   327  
   328  			// Pick the number of asserted elements, then assert
   329  			// random wakers.
   330  			asserted := rand.Int() % (n + 1)
   331  			for j := 0; j < asserted; j++ {
   332  				w[rand.Int()%n].Assert()
   333  			}
   334  			s.Done()
   335  		}
   336  	}
   337  }
   338  
   339  // TestRace tests that multiple wakers can continuously send wake requests to
   340  // the sleeper.
   341  func TestRace(t *testing.T) {
   342  	const wakers = 100
   343  	const wakeRequests = 10000
   344  
   345  	counts := make([]int, wakers)
   346  	w := make([]Waker, wakers)
   347  	s := Sleeper{}
   348  
   349  	// Associate each waker and start goroutines that will assert them.
   350  	for i := range w {
   351  		s.AddWaker(&w[i], i)
   352  		go func(w *Waker) {
   353  			n := 0
   354  			for n < wakeRequests {
   355  				if !w.IsAsserted() {
   356  					w.Assert()
   357  					n++
   358  				} else {
   359  					runtime.Gosched()
   360  				}
   361  			}
   362  		}(&w[i])
   363  	}
   364  
   365  	// Wait for all wake up notifications from all wakers.
   366  	for i := 0; i < wakers*wakeRequests; i++ {
   367  		v, _ := s.Fetch(true)
   368  		counts[v]++
   369  	}
   370  
   371  	// Check that we got the right number for each.
   372  	for i, v := range counts {
   373  		if v != wakeRequests {
   374  			t.Errorf("Waker %v only got %v wakes", i, v)
   375  		}
   376  	}
   377  }
   378  
   379  // BenchmarkSleeperMultiSelect measures how long it takes to fetch a wake up
   380  // from 4 wakers when at least one is already asserted.
   381  func BenchmarkSleeperMultiSelect(b *testing.B) {
   382  	const count = 4
   383  	s := Sleeper{}
   384  	w := make([]Waker, count)
   385  	for i := range w {
   386  		s.AddWaker(&w[i], i)
   387  	}
   388  
   389  	b.ResetTimer()
   390  	for i := 0; i < b.N; i++ {
   391  		w[count-1].Assert()
   392  		s.Fetch(true)
   393  	}
   394  }
   395  
   396  // BenchmarkGoMultiSelect measures how long it takes to fetch a zero-length
   397  // struct from one of 4 channels when at least one is ready.
   398  func BenchmarkGoMultiSelect(b *testing.B) {
   399  	const count = 4
   400  	ch := make([]chan struct{}, count)
   401  	for i := range ch {
   402  		ch[i] = make(chan struct{}, 1)
   403  	}
   404  
   405  	b.ResetTimer()
   406  	for i := 0; i < b.N; i++ {
   407  		ch[count-1] <- struct{}{}
   408  		select {
   409  		case <-ch[0]:
   410  		case <-ch[1]:
   411  		case <-ch[2]:
   412  		case <-ch[3]:
   413  		}
   414  	}
   415  }
   416  
   417  // BenchmarkSleeperSingleSelect measures how long it takes to fetch a wake up
   418  // from one waker that is already asserted.
   419  func BenchmarkSleeperSingleSelect(b *testing.B) {
   420  	s := Sleeper{}
   421  	w := Waker{}
   422  	s.AddWaker(&w, 0)
   423  
   424  	b.ResetTimer()
   425  	for i := 0; i < b.N; i++ {
   426  		w.Assert()
   427  		s.Fetch(true)
   428  	}
   429  }
   430  
   431  // BenchmarkGoSingleSelect measures how long it takes to fetch a zero-length
   432  // struct from a channel that already has it buffered.
   433  func BenchmarkGoSingleSelect(b *testing.B) {
   434  	ch := make(chan struct{}, 1)
   435  
   436  	b.ResetTimer()
   437  	for i := 0; i < b.N; i++ {
   438  		ch <- struct{}{}
   439  		<-ch
   440  	}
   441  }
   442  
   443  // BenchmarkSleeperAssertNonWaiting measures how long it takes to assert a
   444  // channel that is already asserted.
   445  func BenchmarkSleeperAssertNonWaiting(b *testing.B) {
   446  	w := Waker{}
   447  	w.Assert()
   448  	for i := 0; i < b.N; i++ {
   449  		w.Assert()
   450  	}
   451  
   452  }
   453  
   454  // BenchmarkGoAssertNonWaiting measures how long it takes to write to a channel
   455  // that has already something written to it.
   456  func BenchmarkGoAssertNonWaiting(b *testing.B) {
   457  	ch := make(chan struct{}, 1)
   458  	ch <- struct{}{}
   459  	for i := 0; i < b.N; i++ {
   460  		select {
   461  		case ch <- struct{}{}:
   462  		default:
   463  		}
   464  	}
   465  }
   466  
   467  // BenchmarkSleeperWaitOnSingleSelect measures how long it takes to wait on one
   468  // waker channel while another goroutine wakes up the sleeper. This assumes that
   469  // a new goroutine doesn't run immediately (i.e., the creator of a new goroutine
   470  // is allowed to go to sleep before the new goroutine has a chance to run).
   471  func BenchmarkSleeperWaitOnSingleSelect(b *testing.B) {
   472  	s := Sleeper{}
   473  	w := Waker{}
   474  	s.AddWaker(&w, 0)
   475  	for i := 0; i < b.N; i++ {
   476  		go func() {
   477  			w.Assert()
   478  		}()
   479  		s.Fetch(true)
   480  	}
   481  
   482  }
   483  
   484  // BenchmarkGoWaitOnSingleSelect measures how long it takes to wait on one
   485  // channel while another goroutine wakes up the sleeper. This assumes that a new
   486  // goroutine doesn't run immediately (i.e., the creator of a new goroutine is
   487  // allowed to go to sleep before the new goroutine has a chance to run).
   488  func BenchmarkGoWaitOnSingleSelect(b *testing.B) {
   489  	ch := make(chan struct{}, 1)
   490  	for i := 0; i < b.N; i++ {
   491  		go func() {
   492  			ch <- struct{}{}
   493  		}()
   494  		<-ch
   495  	}
   496  }
   497  
   498  // BenchmarkSleeperWaitOnMultiSelect measures how long it takes to wait on 4
   499  // wakers while another goroutine wakes up the sleeper. This assumes that a new
   500  // goroutine doesn't run immediately (i.e., the creator of a new goroutine is
   501  // allowed to go to sleep before the new goroutine has a chance to run).
   502  func BenchmarkSleeperWaitOnMultiSelect(b *testing.B) {
   503  	const count = 4
   504  	s := Sleeper{}
   505  	w := make([]Waker, count)
   506  	for i := range w {
   507  		s.AddWaker(&w[i], i)
   508  	}
   509  
   510  	b.ResetTimer()
   511  	for i := 0; i < b.N; i++ {
   512  		go func() {
   513  			w[count-1].Assert()
   514  		}()
   515  		s.Fetch(true)
   516  	}
   517  }
   518  
   519  // BenchmarkGoWaitOnMultiSelect measures how long it takes to wait on 4 channels
   520  // while another goroutine wakes up the sleeper. This assumes that a new
   521  // goroutine doesn't run immediately (i.e., the creator of a new goroutine is
   522  // allowed to go to sleep before the new goroutine has a chance to run).
   523  func BenchmarkGoWaitOnMultiSelect(b *testing.B) {
   524  	const count = 4
   525  	ch := make([]chan struct{}, count)
   526  	for i := range ch {
   527  		ch[i] = make(chan struct{}, 1)
   528  	}
   529  
   530  	b.ResetTimer()
   531  	for i := 0; i < b.N; i++ {
   532  		go func() {
   533  			ch[count-1] <- struct{}{}
   534  		}()
   535  		select {
   536  		case <-ch[0]:
   537  		case <-ch[1]:
   538  		case <-ch[2]:
   539  		case <-ch[3]:
   540  		}
   541  	}
   542  }