github.com/fafucoder/cilium@v1.6.11/pkg/completion/completion_test.go (about)

     1  // Copyright 2018 Authors of Cilium
     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  // +build !privileged_tests
    16  
    17  package completion
    18  
    19  import (
    20  	"errors"
    21  	"testing"
    22  	"time"
    23  
    24  	"context"
    25  	. "gopkg.in/check.v1"
    26  )
    27  
    28  // Hook up gocheck into the "go test" runner.
    29  func Test(t *testing.T) {
    30  	//logging.ToggleDebugLogs(true)
    31  	TestingT(t)
    32  }
    33  
    34  type CompletionSuite struct{}
    35  
    36  var _ = Suite(&CompletionSuite{})
    37  
    38  const (
    39  	TestTimeout      = 10 * time.Second
    40  	WaitGroupTimeout = 250 * time.Millisecond
    41  	CompletionDelay  = 250 * time.Millisecond
    42  )
    43  
    44  func (s *CompletionSuite) TestNoCompletion(c *C) {
    45  	var err error
    46  
    47  	ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
    48  	defer cancel()
    49  
    50  	wg := NewWaitGroup(ctx)
    51  
    52  	// Wait should return immediately, since there are no completions.
    53  	err = wg.Wait()
    54  	c.Assert(err, IsNil)
    55  }
    56  
    57  func (s *CompletionSuite) TestCompletionBeforeWait(c *C) {
    58  	var err error
    59  
    60  	ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
    61  	defer cancel()
    62  
    63  	wg := NewWaitGroup(ctx)
    64  
    65  	comp := wg.AddCompletion()
    66  
    67  	comp.Complete(nil)
    68  
    69  	// Wait should return immediately, since the only completion is already completed.
    70  	err = wg.Wait()
    71  	c.Assert(err, IsNil)
    72  }
    73  
    74  func (s *CompletionSuite) TestCompletionAfterWait(c *C) {
    75  	var err error
    76  
    77  	ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
    78  	defer cancel()
    79  
    80  	wg := NewWaitGroup(ctx)
    81  
    82  	comp := wg.AddCompletion()
    83  
    84  	go func() {
    85  		time.Sleep(CompletionDelay)
    86  		comp.Complete(nil)
    87  	}()
    88  
    89  	// Wait should block until comp.Complete is called, then return nil.
    90  	err = wg.Wait()
    91  	c.Assert(err, IsNil)
    92  }
    93  
    94  func (s *CompletionSuite) TestCompletionBeforeAndAfterWait(c *C) {
    95  	var err error
    96  
    97  	ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
    98  	defer cancel()
    99  
   100  	wg := NewWaitGroup(ctx)
   101  
   102  	comp1 := wg.AddCompletion()
   103  
   104  	comp2 := wg.AddCompletion()
   105  
   106  	comp1.Complete(nil)
   107  
   108  	go func() {
   109  		time.Sleep(CompletionDelay)
   110  		comp2.Complete(nil)
   111  	}()
   112  
   113  	// Wait should block until comp2.Complete is called, then return nil.
   114  	err = wg.Wait()
   115  	c.Assert(err, IsNil)
   116  }
   117  
   118  func (s *CompletionSuite) TestCompletionTimeout(c *C) {
   119  	var err error
   120  
   121  	ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
   122  	defer cancel()
   123  
   124  	// Set a shorter timeout to shorten the test duration.
   125  	wgCtx, cancel := context.WithTimeout(ctx, WaitGroupTimeout)
   126  	defer cancel()
   127  	wg := NewWaitGroup(wgCtx)
   128  
   129  	comp := wg.AddCompletionWithCallback(func(err error) {
   130  		// Callback gets called with context.DeadlineExceeded if the WaitGroup times out
   131  		c.Assert(err, Equals, context.DeadlineExceeded)
   132  	})
   133  
   134  	// comp never completes.
   135  
   136  	// Wait should block until wgCtx expires.
   137  	err = wg.Wait()
   138  	c.Assert(err, Not(IsNil))
   139  	c.Assert(err, Equals, wgCtx.Err())
   140  
   141  	// Complete is idempotent and harmless, and can be called after the
   142  	// context is canceled.
   143  	comp.Complete(nil)
   144  }
   145  
   146  func (s *CompletionSuite) TestCompletionMultipleCompleteCalls(c *C) {
   147  	var err error
   148  
   149  	ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
   150  	defer cancel()
   151  
   152  	// Set a shorter timeout to shorten the test duration.
   153  	wg := NewWaitGroup(ctx)
   154  
   155  	comp := wg.AddCompletion()
   156  
   157  	// Complete is idempotent.
   158  	comp.Complete(nil)
   159  	comp.Complete(nil)
   160  	comp.Complete(nil)
   161  
   162  	// Wait should return immediately, since the only completion is already completed.
   163  	err = wg.Wait()
   164  	c.Assert(err, IsNil)
   165  }
   166  
   167  func (s *CompletionSuite) TestCompletionWithCallback(c *C) {
   168  	var err error
   169  	var callbackCount int
   170  
   171  	ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
   172  	defer cancel()
   173  
   174  	// Set a shorter timeout to shorten the test duration.
   175  	wg := NewWaitGroup(ctx)
   176  
   177  	comp := wg.AddCompletionWithCallback(func(err error) {
   178  		if err == nil {
   179  			callbackCount++
   180  		}
   181  	})
   182  
   183  	// Complete is idempotent.
   184  	comp.Complete(nil)
   185  	comp.Complete(nil)
   186  	comp.Complete(nil)
   187  
   188  	// The callback is called exactly once.
   189  	c.Assert(callbackCount, Equals, 1)
   190  
   191  	// Wait should return immediately, since the only completion is already completed.
   192  	err = wg.Wait()
   193  	c.Assert(err, IsNil)
   194  }
   195  
   196  func (s *CompletionSuite) TestCompletionWithCallbackError(c *C) {
   197  	var err error
   198  	var callbackCount, callbackCount2 int
   199  
   200  	ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
   201  	defer cancel()
   202  
   203  	err1 := errors.New("Error1")
   204  	err2 := errors.New("Error2")
   205  
   206  	// Set a shorter timeout to shorten the test duration.
   207  	wg := NewWaitGroup(ctx)
   208  
   209  	comp := wg.AddCompletionWithCallback(func(err error) {
   210  		callbackCount++
   211  		// Completion that completes with a failure gets the reason for the failure
   212  		c.Assert(err, Equals, err1)
   213  	})
   214  
   215  	wg.AddCompletionWithCallback(func(err error) {
   216  		callbackCount2++
   217  		// When one completions fail the other completion callbacks
   218  		// are called with context.Canceled
   219  		c.Assert(err, Equals, context.Canceled)
   220  	})
   221  
   222  	// Complete is idempotent.
   223  	comp.Complete(err1)
   224  	comp.Complete(err2)
   225  	comp.Complete(nil)
   226  
   227  	// Wait should return immediately, since the only completion is already completed.
   228  	err = wg.Wait()
   229  	c.Assert(err, Equals, err1)
   230  
   231  	// The callbacks are called exactly once.
   232  	c.Assert(callbackCount, Equals, 1)
   233  	c.Assert(callbackCount2, Equals, 1)
   234  }
   235  
   236  func (s *CompletionSuite) TestCompletionWithCallbackOtherError(c *C) {
   237  	var err error
   238  	var callbackCount, callbackCount2 int
   239  
   240  	ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
   241  	defer cancel()
   242  
   243  	err1 := errors.New("Error1")
   244  	err2 := errors.New("Error2")
   245  
   246  	// Set a shorter timeout to shorten the test duration.
   247  	wg := NewWaitGroup(ctx)
   248  
   249  	wg.AddCompletionWithCallback(func(err error) {
   250  		callbackCount++
   251  		c.Assert(err, Equals, context.Canceled)
   252  	})
   253  
   254  	comp2 := wg.AddCompletionWithCallback(func(err error) {
   255  		callbackCount2++
   256  		c.Assert(err, Equals, err2)
   257  	})
   258  
   259  	// Complete is idempotent.
   260  	comp2.Complete(err2)
   261  	comp2.Complete(err1)
   262  	comp2.Complete(nil)
   263  
   264  	// Wait should return immediately, since the only completion is already completed.
   265  	err = wg.Wait()
   266  	c.Assert(err, Equals, err2)
   267  
   268  	// The callbacks are called exactly once.
   269  	c.Assert(callbackCount, Equals, 1)
   270  	c.Assert(callbackCount2, Equals, 1)
   271  }
   272  
   273  func (s *CompletionSuite) TestCompletionWithCallbackTimeout(c *C) {
   274  	var err error
   275  	var callbackCount int
   276  
   277  	ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
   278  	defer cancel()
   279  
   280  	// Set a shorter timeout to shorten the test duration.
   281  	wgCtx, cancel := context.WithTimeout(ctx, WaitGroupTimeout)
   282  	defer cancel()
   283  	wg := NewWaitGroup(wgCtx)
   284  
   285  	comp := wg.AddCompletionWithCallback(func(err error) {
   286  		if err == nil {
   287  			callbackCount++
   288  		}
   289  		c.Assert(err, Equals, context.DeadlineExceeded)
   290  	})
   291  
   292  	// comp never completes.
   293  
   294  	// Wait should block until wgCtx expires.
   295  	err = wg.Wait()
   296  	c.Assert(err, Not(IsNil))
   297  	c.Assert(err, Equals, wgCtx.Err())
   298  
   299  	// Complete is idempotent and harmless, and can be called after the
   300  	// context is canceled.
   301  	comp.Complete(nil)
   302  
   303  	// The callback is only called with the error 'context.DeadlineExceeded'.
   304  	c.Assert(callbackCount, Equals, 0)
   305  }