
In particular ExpectNoError needed testing, as it was unused so far and not functional in its initial implementation.
272 lines
7.4 KiB
Go
272 lines
7.4 KiB
Go
/*
|
|
Copyright 2024 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package ktesting
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/onsi/gomega"
|
|
)
|
|
|
|
func TestAssert(t *testing.T) {
|
|
for name, tc := range map[string]testcase{
|
|
"eventually-timeout": {
|
|
cb: func(tCtx TContext) {
|
|
Eventually(tCtx, func(tCtx TContext) int {
|
|
// Canceling here is a nop.
|
|
tCtx.Cancel("testing")
|
|
return 0
|
|
}).WithTimeout(time.Second).Should(gomega.Equal(1))
|
|
},
|
|
expectDuration: time.Second,
|
|
expectError: `Timed out after x.y s.
|
|
Expected
|
|
<int>: 0
|
|
to equal
|
|
<int>: 1`,
|
|
},
|
|
"eventually-final": {
|
|
cb: func(tCtx TContext) {
|
|
Eventually(tCtx, func(tCtx TContext) float64 {
|
|
gomega.StopTrying("final error").Now()
|
|
return 0
|
|
}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
|
|
},
|
|
expectDuration: 0,
|
|
expectError: `Told to stop trying after x.y s.
|
|
final error`,
|
|
},
|
|
"eventually-error": {
|
|
cb: func(tCtx TContext) {
|
|
Eventually(tCtx, func(tCtx TContext) float64 {
|
|
tCtx.Fatal("some error")
|
|
return 0
|
|
}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
|
|
},
|
|
expectDuration: time.Second,
|
|
expectError: `Timed out after x.y s.
|
|
The function passed to Eventually returned the following error:
|
|
<*errors.joinError | 0xXXXX>:
|
|
some error
|
|
{
|
|
errs: [
|
|
<*errors.errorString | 0xXXXX>{s: "some error"},
|
|
],
|
|
}`,
|
|
},
|
|
"eventually-success": {
|
|
cb: func(tCtx TContext) {
|
|
Eventually(tCtx, func(tCtx TContext) float64 {
|
|
return 1.0
|
|
}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
|
|
},
|
|
expectDuration: 0,
|
|
expectNoFail: true,
|
|
expectError: ``,
|
|
},
|
|
"eventually-retry": {
|
|
cb: func(tCtx TContext) {
|
|
Eventually(tCtx, func(tCtx TContext) float64 {
|
|
gomega.TryAgainAfter(time.Millisecond).Now()
|
|
return 0
|
|
}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
|
|
},
|
|
expectDuration: time.Second,
|
|
expectError: `Timed out after x.y s.
|
|
told to try again after 1ms`,
|
|
},
|
|
"consistently-timeout": {
|
|
cb: func(tCtx TContext) {
|
|
Consistently(tCtx, func(tCtx TContext) float64 {
|
|
// Canceling here is a nop.
|
|
tCtx.Cancel("testing")
|
|
return 0
|
|
}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
|
|
},
|
|
expectDuration: 0,
|
|
expectError: `Failed after x.y s.
|
|
Expected
|
|
<float64>: 0
|
|
to equal
|
|
<float64>: 1`,
|
|
},
|
|
"consistently-final": {
|
|
cb: func(tCtx TContext) {
|
|
Consistently(tCtx, func(tCtx TContext) float64 {
|
|
gomega.StopTrying("final error").Now()
|
|
tCtx.FailNow()
|
|
return 0
|
|
}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
|
|
},
|
|
expectDuration: 0,
|
|
expectError: `Told to stop trying after x.y s.
|
|
final error`,
|
|
},
|
|
"consistently-error": {
|
|
cb: func(tCtx TContext) {
|
|
Consistently(tCtx, func(tCtx TContext) float64 {
|
|
tCtx.Fatal("some error")
|
|
return 0
|
|
}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
|
|
},
|
|
expectDuration: 0,
|
|
expectError: `Failed after x.y s.
|
|
The function passed to Consistently returned the following error:
|
|
<*errors.joinError | 0xXXXX>:
|
|
some error
|
|
{
|
|
errs: [
|
|
<*errors.errorString | 0xXXXX>{s: "some error"},
|
|
],
|
|
}`,
|
|
},
|
|
"consistently-success": {
|
|
cb: func(tCtx TContext) {
|
|
Consistently(tCtx, func(tCtx TContext) float64 {
|
|
return 1.0
|
|
}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
|
|
},
|
|
expectDuration: time.Second,
|
|
expectNoFail: true,
|
|
expectError: ``,
|
|
},
|
|
"consistently-retry": {
|
|
cb: func(tCtx TContext) {
|
|
Consistently(tCtx, func(tCtx TContext) float64 {
|
|
gomega.TryAgainAfter(time.Millisecond).Wrap(errors.New("intermittent error")).Now()
|
|
return 0
|
|
}).WithTimeout(time.Second).Should(gomega.Equal(1.0))
|
|
},
|
|
expectDuration: time.Second,
|
|
expectError: `Timed out while waiting on TryAgainAfter after x.y s.
|
|
told to try again after 1ms: intermittent error`,
|
|
},
|
|
|
|
"expect-equal": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.Expect(1).To(gomega.Equal(42))
|
|
},
|
|
expectError: `Expected
|
|
<int>: 1
|
|
to equal
|
|
<int>: 42`,
|
|
},
|
|
|
|
"expect-no-error-success": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.ExpectNoError(nil)
|
|
},
|
|
expectNoFail: true,
|
|
},
|
|
"expect-no-error-normal-error": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.ExpectNoError(errors.New("fake error"))
|
|
},
|
|
expectError: `Unexpected error: fake error`,
|
|
expectLog: `<klog header>: Unexpected error:
|
|
<*errors.errorString | 0xXXXX>:
|
|
fake error
|
|
{s: "fake error"}
|
|
`,
|
|
},
|
|
"expect-no-error-failure": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error"}))
|
|
},
|
|
expectError: `doing something: fake error`,
|
|
},
|
|
"expect-no-error-explanation-string": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error"}), "testing error checking")
|
|
},
|
|
expectError: `testing error checking: doing something: fake error`,
|
|
},
|
|
"expect-no-error-explanation-printf": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error"}), "testing %s %d checking", "error", 42)
|
|
},
|
|
expectError: `testing error 42 checking: doing something: fake error`,
|
|
},
|
|
"expect-no-error-explanation-callback": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error"}), func() string { return "testing error checking" })
|
|
},
|
|
expectError: `testing error checking: doing something: fake error`,
|
|
},
|
|
"expect-no-error-backtrace": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error", FullStackTrace: "abc\nxyz"}))
|
|
},
|
|
expectError: `doing something: fake error`,
|
|
expectLog: `<klog header>: Failed at:
|
|
abc
|
|
xyz
|
|
`,
|
|
},
|
|
"expect-no-error-backtrace-and-explanation": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.ExpectNoError(fmt.Errorf("doing something: %w", FailureError{Msg: "fake error", FullStackTrace: "abc\nxyz"}), "testing error checking")
|
|
},
|
|
expectError: `testing error checking: doing something: fake error`,
|
|
expectLog: `<klog header>: testing error checking
|
|
<klog header>: Failed at:
|
|
abc
|
|
xyz
|
|
`,
|
|
},
|
|
|
|
"output": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.Log("Log", "a", "b", 42)
|
|
tCtx.Logf("Logf %s %s %d", "a", "b", 42)
|
|
tCtx.Error("Error", "a", "b", 42)
|
|
tCtx.Errorf("Errorf %s %s %d", "a", "b", 42)
|
|
},
|
|
expectLog: `<klog header>: Log a b 42
|
|
<klog header>: Logf a b 42
|
|
`,
|
|
expectError: `Error a b 42
|
|
Errorf a b 42`,
|
|
},
|
|
"fatal": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.Fatal("Error", "a", "b", 42)
|
|
// not reached
|
|
tCtx.Log("Log")
|
|
},
|
|
expectError: `Error a b 42`,
|
|
},
|
|
"fatalf": {
|
|
cb: func(tCtx TContext) {
|
|
tCtx.Fatalf("Error %s %s %d", "a", "b", 42)
|
|
// not reached
|
|
tCtx.Log("Log")
|
|
},
|
|
expectError: `Error a b 42`,
|
|
},
|
|
} {
|
|
tc := tc
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
tc.run(t)
|
|
})
|
|
}
|
|
}
|