...

Source file src/k8s.io/kubernetes/test/utils/ktesting/assert_test.go

Documentation: k8s.io/kubernetes/test/utils/ktesting

     1  /*
     2  Copyright 2024 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 ktesting
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/onsi/gomega"
    26  )
    27  
    28  func TestAssert(t *testing.T) {
    29  	for name, tc := range map[string]testcase{
    30  		"eventually-timeout": {
    31  			cb: func(tCtx TContext) {
    32  				Eventually(tCtx, func(tCtx TContext) int {
    33  					// Canceling here is a nop.
    34  					tCtx.Cancel("testing")
    35  					return 0
    36  				}).WithTimeout(time.Second).Should(gomega.Equal(1))
    37  			},
    38  			expectDuration: time.Second,
    39  			expectError: `Timed out after x.y s.
    40  Expected
    41      <int>: 0
    42  to equal
    43      <int>: 1`,
    44  		},
    45  		"eventually-final": {
    46  			cb: func(tCtx TContext) {
    47  				Eventually(tCtx, func(tCtx TContext) float64 {
    48  					gomega.StopTrying("final error").Now()
    49  					return 0
    50  				}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
    51  			},
    52  			expectDuration: 0,
    53  			expectError: `Told to stop trying after x.y s.
    54  final error`,
    55  		},
    56  		"eventually-error": {
    57  			cb: func(tCtx TContext) {
    58  				Eventually(tCtx, func(tCtx TContext) float64 {
    59  					tCtx.Fatal("some error")
    60  					return 0
    61  				}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
    62  			},
    63  			expectDuration: time.Second,
    64  			expectError: `Timed out after x.y s.
    65  The function passed to Eventually returned the following error:
    66      <*errors.joinError | 0xXXXX>: 
    67      some error
    68      {
    69          errs: [
    70              <*errors.errorString | 0xXXXX>{s: "some error"},
    71          ],
    72      }`,
    73  		},
    74  		"eventually-success": {
    75  			cb: func(tCtx TContext) {
    76  				Eventually(tCtx, func(tCtx TContext) float64 {
    77  					return 1.0
    78  				}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
    79  			},
    80  			expectDuration: 0,
    81  			expectNoFail:   true,
    82  			expectError:    ``,
    83  		},
    84  		"eventually-retry": {
    85  			cb: func(tCtx TContext) {
    86  				Eventually(tCtx, func(tCtx TContext) float64 {
    87  					gomega.TryAgainAfter(time.Millisecond).Now()
    88  					return 0
    89  				}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
    90  			},
    91  			expectDuration: time.Second,
    92  			expectError: `Timed out after x.y s.
    93  told to try again after 1ms`,
    94  		},
    95  		"consistently-timeout": {
    96  			cb: func(tCtx TContext) {
    97  				Consistently(tCtx, func(tCtx TContext) float64 {
    98  					// Canceling here is a nop.
    99  					tCtx.Cancel("testing")
   100  					return 0
   101  				}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
   102  			},
   103  			expectDuration: 0,
   104  			expectError: `Failed after x.y s.
   105  Expected
   106      <float64>: 0
   107  to equal
   108      <float64>: 1`,
   109  		},
   110  		"consistently-final": {
   111  			cb: func(tCtx TContext) {
   112  				Consistently(tCtx, func(tCtx TContext) float64 {
   113  					gomega.StopTrying("final error").Now()
   114  					tCtx.FailNow()
   115  					return 0
   116  				}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
   117  			},
   118  			expectDuration: 0,
   119  			expectError: `Told to stop trying after x.y s.
   120  final error`,
   121  		},
   122  		"consistently-error": {
   123  			cb: func(tCtx TContext) {
   124  				Consistently(tCtx, func(tCtx TContext) float64 {
   125  					tCtx.Fatal("some error")
   126  					return 0
   127  				}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
   128  			},
   129  			expectDuration: 0,
   130  			expectError: `Failed after x.y s.
   131  The function passed to Consistently returned the following error:
   132      <*errors.joinError | 0xXXXX>: 
   133      some error
   134      {
   135          errs: [
   136              <*errors.errorString | 0xXXXX>{s: "some error"},
   137          ],
   138      }`,
   139  		},
   140  		"consistently-success": {
   141  			cb: func(tCtx TContext) {
   142  				Consistently(tCtx, func(tCtx TContext) float64 {
   143  					return 1.0
   144  				}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
   145  			},
   146  			expectDuration: time.Second,
   147  			expectNoFail:   true,
   148  			expectError:    ``,
   149  		},
   150  		"consistently-retry": {
   151  			cb: func(tCtx TContext) {
   152  				Consistently(tCtx, func(tCtx TContext) float64 {
   153  					gomega.TryAgainAfter(time.Millisecond).Wrap(errors.New("intermittent error")).Now()
   154  					return 0
   155  				}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
   156  			},
   157  			expectDuration: time.Second,
   158  			expectError: `Timed out while waiting on TryAgainAfter after x.y s.
   159  told to try again after 1ms: intermittent error`,
   160  		},
   161  
   162  		"expect-equal": {
   163  			cb: func(tCtx TContext) {
   164  				tCtx.Expect(1).To(gomega.Equal(42))
   165  			},
   166  			expectError: `Expected
   167      <int>: 1
   168  to equal
   169      <int>: 42`,
   170  		},
   171  
   172  		"expect-no-error-success": {
   173  			cb: func(tCtx TContext) {
   174  				tCtx.ExpectNoError(nil)
   175  			},
   176  			expectNoFail: true,
   177  		},
   178  		"expect-no-error-normal-error": {
   179  			cb: func(tCtx TContext) {
   180  				tCtx.ExpectNoError(errors.New("fake error"))
   181  			},
   182  			expectError: `Unexpected error: fake error`,
   183  			expectLog: `<klog header>: Unexpected error:
   184      <*errors.errorString | 0xXXXX>: 
   185      fake error
   186      {s: "fake error"}
   187  `,
   188  		},
   189  		"expect-no-error-failure": {
   190  			cb: func(tCtx TContext) {
   191  				tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error"}))
   192  			},
   193  			expectError: `doing something: fake error`,
   194  		},
   195  		"expect-no-error-explanation-string": {
   196  			cb: func(tCtx TContext) {
   197  				tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error"}), "testing error checking")
   198  			},
   199  			expectError: `testing error checking: doing something: fake error`,
   200  		},
   201  		"expect-no-error-explanation-printf": {
   202  			cb: func(tCtx TContext) {
   203  				tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error"}), "testing %s %d checking", "error", 42)
   204  			},
   205  			expectError: `testing error 42 checking: doing something: fake error`,
   206  		},
   207  		"expect-no-error-explanation-callback": {
   208  			cb: func(tCtx TContext) {
   209  				tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error"}), func() string { return "testing error checking" })
   210  			},
   211  			expectError: `testing error checking: doing something: fake error`,
   212  		},
   213  		"expect-no-error-backtrace": {
   214  			cb: func(tCtx TContext) {
   215  				tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error", FullStackTrace: "abc\nxyz"}))
   216  			},
   217  			expectError: `doing something: fake error`,
   218  			expectLog: `<klog header>: Failed at:
   219      abc
   220      xyz
   221  `,
   222  		},
   223  		"expect-no-error-backtrace-and-explanation": {
   224  			cb: func(tCtx TContext) {
   225  				tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error", FullStackTrace: "abc\nxyz"}), "testing error checking")
   226  			},
   227  			expectError: `testing error checking: doing something: fake error`,
   228  			expectLog: `<klog header>: testing error checking
   229  <klog header>: Failed at:
   230      abc
   231      xyz
   232  `,
   233  		},
   234  
   235  		"output": {
   236  			cb: func(tCtx TContext) {
   237  				tCtx.Log("Log", "a", "b", 42)
   238  				tCtx.Logf("Logf %s %s %d", "a", "b", 42)
   239  				tCtx.Error("Error", "a", "b", 42)
   240  				tCtx.Errorf("Errorf %s %s %d", "a", "b", 42)
   241  			},
   242  			expectLog: `<klog header>: Log a b 42
   243  <klog header>: Logf a b 42
   244  `,
   245  			expectError: `Error a b 42
   246  Errorf a b 42`,
   247  		},
   248  		"fatal": {
   249  			cb: func(tCtx TContext) {
   250  				tCtx.Fatal("Error", "a", "b", 42)
   251  				// not reached
   252  				tCtx.Log("Log")
   253  			},
   254  			expectError: `Error a b 42`,
   255  		},
   256  		"fatalf": {
   257  			cb: func(tCtx TContext) {
   258  				tCtx.Fatalf("Error %s %s %d", "a", "b", 42)
   259  				// not reached
   260  				tCtx.Log("Log")
   261  			},
   262  			expectError: `Error a b 42`,
   263  		},
   264  	} {
   265  		tc := tc
   266  		t.Run(name, func(t *testing.T) {
   267  			t.Parallel()
   268  			tc.run(t)
   269  		})
   270  	}
   271  }
   272  

View as plain text