github.com/elfadel/cilium@v1.6.12/pkg/status/status_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 status
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"strings"
    23  	"sync/atomic"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/cilium/cilium/pkg/testutils"
    28  
    29  	. "gopkg.in/check.v1"
    30  )
    31  
    32  type StatusTestSuite struct {
    33  	config Config
    34  }
    35  
    36  var _ = Suite(&StatusTestSuite{})
    37  
    38  func Test(t *testing.T) {
    39  	TestingT(t)
    40  }
    41  
    42  func (s *StatusTestSuite) SetUpTest(c *C) {
    43  	s.config = Config{
    44  		Interval:         10 * time.Millisecond,
    45  		WarningThreshold: 20 * time.Millisecond,
    46  		FailureThreshold: 80 * time.Millisecond,
    47  	}
    48  }
    49  
    50  func (s *StatusTestSuite) TestVariableProbeInterval(c *C) {
    51  	var runs, ok uint64
    52  
    53  	p := []Probe{
    54  		{
    55  			Interval: func(failures int) time.Duration {
    56  				// While failing, retry every millisecond
    57  				if failures > 0 {
    58  					return time.Millisecond
    59  				}
    60  
    61  				// Ensure that the regular interval would never retry
    62  				return time.Minute
    63  			},
    64  			Probe: func(ctx context.Context) (interface{}, error) {
    65  				// Let 5 runs fail and then succeed
    66  				atomic.AddUint64(&runs, 1)
    67  				if atomic.LoadUint64(&runs) < 5 {
    68  					return nil, fmt.Errorf("still failing")
    69  				}
    70  
    71  				return nil, nil
    72  			},
    73  			OnStatusUpdate: func(status Status) {
    74  				if status.Data == nil && status.Err == nil {
    75  					atomic.AddUint64(&ok, 1)
    76  				}
    77  			},
    78  		},
    79  	}
    80  
    81  	collector := NewCollector(p, s.config)
    82  	defer collector.Close()
    83  
    84  	// wait for 5 probe intervals to occur with 1 millisecond interval
    85  	// until we reach success
    86  	c.Assert(testutils.WaitUntil(func() bool {
    87  		return atomic.LoadUint64(&ok) >= 1
    88  	}, 1*time.Second), IsNil)
    89  }
    90  
    91  func (s *StatusTestSuite) TestCollectorFailureTimeout(c *C) {
    92  	var ok uint64
    93  
    94  	p := []Probe{
    95  		{
    96  			Probe: func(ctx context.Context) (interface{}, error) {
    97  				time.Sleep(s.config.FailureThreshold * 2)
    98  				return nil, nil
    99  			},
   100  			OnStatusUpdate: func(status Status) {
   101  				if status.StaleWarning && status.Data == nil && status.Err != nil {
   102  					if strings.Contains(status.Err.Error(),
   103  						fmt.Sprintf("within %v seconds", s.config.FailureThreshold.Seconds())) {
   104  
   105  						atomic.AddUint64(&ok, 1)
   106  					}
   107  				}
   108  			},
   109  		},
   110  	}
   111  
   112  	collector := NewCollector(p, s.config)
   113  	defer collector.Close()
   114  
   115  	// wait for the failure timeout to kick in
   116  	c.Assert(testutils.WaitUntil(func() bool {
   117  		return atomic.LoadUint64(&ok) >= 1
   118  	}, 1*time.Second), IsNil)
   119  	c.Assert(collector.GetStaleProbes(), HasLen, 1)
   120  }
   121  
   122  func (s *StatusTestSuite) TestCollectorSuccess(c *C) {
   123  	var ok, errors uint64
   124  	err := fmt.Errorf("error")
   125  
   126  	p := []Probe{
   127  		{
   128  			Probe: func(ctx context.Context) (interface{}, error) {
   129  				if atomic.LoadUint64(&ok) > 3 {
   130  					return nil, err
   131  				}
   132  				return "testData", nil
   133  			},
   134  			OnStatusUpdate: func(status Status) {
   135  				if status.Err == err {
   136  					atomic.AddUint64(&errors, 1)
   137  				}
   138  				if !status.StaleWarning && status.Data != nil && status.Err == nil {
   139  					if s, isString := status.Data.(string); isString && s == "testData" {
   140  						atomic.AddUint64(&ok, 1)
   141  					}
   142  				}
   143  			},
   144  		},
   145  	}
   146  
   147  	collector := NewCollector(p, s.config)
   148  	defer collector.Close()
   149  
   150  	// wait for the probe to succeed 3 times and to return the error 3 times
   151  	c.Assert(testutils.WaitUntil(func() bool {
   152  		return atomic.LoadUint64(&ok) >= 3 && atomic.LoadUint64(&errors) >= 3
   153  	}, 1*time.Second), IsNil)
   154  	c.Assert(collector.GetStaleProbes(), HasLen, 0)
   155  }
   156  
   157  func (s *StatusTestSuite) TestCollectorSuccessAfterTimeout(c *C) {
   158  	var ok, timeout uint64
   159  
   160  	p := []Probe{
   161  		{
   162  			Probe: func(ctx context.Context) (interface{}, error) {
   163  				if atomic.LoadUint64(&timeout) == 0 {
   164  					time.Sleep(2 * s.config.FailureThreshold)
   165  				}
   166  				return nil, nil
   167  			},
   168  			OnStatusUpdate: func(status Status) {
   169  				if status.StaleWarning {
   170  					atomic.AddUint64(&timeout, 1)
   171  				} else {
   172  					atomic.AddUint64(&ok, 1)
   173  				}
   174  
   175  			},
   176  		},
   177  	}
   178  
   179  	collector := NewCollector(p, s.config)
   180  	defer collector.Close()
   181  
   182  	// wait for the probe to timeout (warning and failure) and then to succeed
   183  	c.Assert(testutils.WaitUntil(func() bool {
   184  		return atomic.LoadUint64(&timeout) == 1 && atomic.LoadUint64(&ok) > 0
   185  	}, 1*time.Second), IsNil)
   186  	c.Assert(collector.GetStaleProbes(), HasLen, 0)
   187  }