diff --git a/internal/mock/common_test.go b/internal/mock/common_test.go index 5c0d7b8..db6deee 100644 --- a/internal/mock/common_test.go +++ b/internal/mock/common_test.go @@ -124,14 +124,12 @@ func methodsMockIFaceFunc(mocktest, test, mock string) []*Method { }, { Name: "err", Type: "error", }}, - Variadic: false, }, { Name: "CallC", Params: []*Param{{ Name: "test", Type: aliasType(test, "Context"), }}, - Results: []*Param{}, - Variadic: false, + Results: []*Param{}, }} } @@ -172,13 +170,25 @@ var ( pathTest, pathTesting, pathMock) methodsTestTest = []*Method{{ + Name: "Cleanup", + Params: []*Param{ + {Name: "cleanup", Type: "func()"}, + }, + Results: []*Param{}, + }, { Name: "Deadline", Params: []*Param{}, Results: []*Param{ {Name: "deadline", Type: "time.Time"}, {Name: "ok", Type: "bool"}, }, - Variadic: false, + }, { + Name: "Error", + Params: []*Param{ + {Name: "args", Type: "[]any"}, + }, + Results: []*Param{}, + Variadic: true, }, { Name: "Errorf", Params: []*Param{ @@ -188,10 +198,24 @@ var ( Results: []*Param{}, Variadic: true, }, { - Name: "FailNow", - Params: []*Param{}, + Name: "Fail", + Params: []*Param{}, + Results: []*Param{}, + }, { + Name: "FailNow", + Params: []*Param{}, + Results: []*Param{}, + }, { + Name: "Failed", + Params: []*Param{}, + Results: []*Param{{Type: "bool"}}, + }, { + Name: "Fatal", + Params: []*Param{ + {Name: "args", Type: "[]any"}, + }, Results: []*Param{}, - Variadic: false, + Variadic: true, }, { Name: "Fatalf", Params: []*Param{ @@ -201,36 +225,76 @@ var ( Results: []*Param{}, Variadic: true, }, { - Name: "Helper", - Params: []*Param{}, - Results: []*Param{}, - Variadic: false, + Name: "Helper", + Params: []*Param{}, + Results: []*Param{}, }, { - Name: "Name", - Params: []*Param{}, - Results: []*Param{{Type: "string"}}, - Variadic: false, + Name: "Log", + Params: []*Param{ + {Name: "args", Type: "[]any"}, + }, + Results: []*Param{}, + Variadic: true, }, { - Name: "Parallel", - Params: []*Param{}, + Name: "Logf", + Params: []*Param{ + {Name: "format", Type: "string"}, + {Name: "args", Type: "[]any"}, + }, Results: []*Param{}, - Variadic: false, + Variadic: true, + }, { + Name: "Name", + Params: []*Param{}, + Results: []*Param{{Type: "string"}}, + }, { + Name: "Parallel", + Params: []*Param{}, + Results: []*Param{}, }, { Name: "Setenv", Params: []*Param{ {Name: "key", Type: "string"}, {Name: "value", Type: "string"}, }, + Results: []*Param{}, + }, { + Name: "Skip", + Params: []*Param{ + {Name: "args", Type: "[]any"}, + }, + Results: []*Param{}, + Variadic: true, + }, { + Name: "SkipNow", + Params: []*Param{}, + Results: []*Param{}, + }, { + Name: "Skipf", + Params: []*Param{ + {Name: "format", Type: "string"}, + {Name: "args", Type: "[]any"}, + }, Results: []*Param{}, - Variadic: false, + Variadic: true, }, { - Name: "TempDir", - Params: []*Param{}, - Results: []*Param{{Type: "string"}}, - Variadic: false, + Name: "Skipped", + Params: []*Param{}, + Results: []*Param{{Type: "bool"}}, + }, { + Name: "TempDir", + Params: []*Param{}, + Results: []*Param{{Type: "string"}}, }} methodsTestReporter = []*Method{{ + Name: "Error", + Params: []*Param{ + {Name: "args", Type: "[]any"}, + }, + Results: []*Param{}, + Variadic: true, + }, { Name: "Errorf", Params: []*Param{ {Name: "format", Type: "string"}, @@ -239,10 +303,20 @@ var ( Results: []*Param{}, Variadic: true, }, { - Name: "FailNow", - Params: []*Param{}, + Name: "Fail", + Params: []*Param{}, + Results: []*Param{}, + }, { + Name: "FailNow", + Params: []*Param{}, + Results: []*Param{}, + }, { + Name: "Fatal", + Params: []*Param{ + {Name: "args", Type: "[]any"}, + }, Results: []*Param{}, - Variadic: false, + Variadic: true, }, { Name: "Fatalf", Params: []*Param{ @@ -252,10 +326,9 @@ var ( Results: []*Param{}, Variadic: true, }, { - Name: "Panic", - Params: []*Param{{Name: "arg", Type: "any"}}, - Results: []*Param{}, - Variadic: false, + Name: "Panic", + Params: []*Param{{Name: "arg", Type: "any"}}, + Results: []*Param{}, }} methodsGoMockTestReporter = []*Method{{ diff --git a/test/caller_test.go b/test/caller_test.go index e4652a1..15fa4c9 100644 --- a/test/caller_test.go +++ b/test/caller_test.go @@ -20,6 +20,13 @@ type Caller struct { path string } +// Error is the caller reporter function to capture the callers file and line +// number of the `Error` call. +func (c *Caller) Error(_ ...any) { + _, path, line, _ := runtime.Caller(1) + c.path = path + ":" + strconv.Itoa(line) +} + // Errorf is the caller reporter function to capture the callers file and line // number of the `Errorf` call. func (c *Caller) Errorf(_ string, _ ...any) { @@ -27,6 +34,14 @@ func (c *Caller) Errorf(_ string, _ ...any) { c.path = path + ":" + strconv.Itoa(line) } +// Fatal is the caller reporter function to capture the callers file and line +// number of the `Fatal` call. +func (c *Caller) Fatal(_ ...any) { + _, path, line, _ := runtime.Caller(1) + c.path = path + ":" + strconv.Itoa(line) + panic("finished") // prevents goexit. +} + // Fatalf is the caller reporter function to capture the callers file and line // number of the `Fatalf` call. func (c *Caller) Fatalf(_ string, _ ...any) { @@ -35,6 +50,14 @@ func (c *Caller) Fatalf(_ string, _ ...any) { panic("finished") // prevents goexit. } +// Fail is the caller reporter function to capture the callers file and line +// number of the `Fail` call. +func (c *Caller) Fail() { + _, path, line, _ := runtime.Caller(1) + c.path = path + ":" + strconv.Itoa(line) + panic("finished") // prevents goexit. +} + // FailNow is the caller reporter function to capture the callers file and line // number of the `FailNow` call. func (c *Caller) FailNow() { @@ -43,6 +66,8 @@ func (c *Caller) FailNow() { panic("finished") // prevents goexit. } +// Panic is the caller reporter function to capture the callers file and line +// number of the `Panic` call. func (c *Caller) Panic(_ any) { _, path, line, _ := runtime.Caller(1) c.path = path + ":" + strconv.Itoa(line) @@ -67,14 +92,26 @@ func getCaller(call func(t test.Reporter)) string { } var ( + // CallerError provides the file with line number of the `Error` call. + CallerError = getCaller(func(t test.Reporter) { + t.Error("fail") + }) // CallerErrorf provides the file with line number of the `Errorf` call. CallerErrorf = getCaller(func(t test.Reporter) { t.Errorf("fail") }) + // CallerFatal provides the file with line number of the `Fatal` call. + CallerFatal = getCaller(func(t test.Reporter) { + t.Fatal("fail") + }) // CallerFatalf provides the file with line number of the `Fatalf` call. CallerFatalf = getCaller(func(t test.Reporter) { t.Fatalf("fail") }) + // CallerFail provides the file with line number of the `Fail` call. + CallerFail = getCaller(func(t test.Reporter) { + t.Fail() + }) // CallerFailNow provides the file with line number of the `FailNow` call. CallerFailNow = getCaller(func(t test.Reporter) { t.FailNow() @@ -92,10 +129,17 @@ var ( } return dir }() + // CallerTestError provides the file with the line number of the `Error` + // call in the test context implementation. + CallerTestError = path.Join(SourceDir, "context.go:356") + // CallerReporterErrorf provides the file with the line number of the + // `Errorf` call in the test reporter/validator implementation. + CallerReporterError = path.Join(SourceDir, "gomock.go:60") + // CallerTestErrorf provides the file with the line number of the `Errorf` // call in the test context implementation. - CallerTestErrorf = path.Join(SourceDir, "context.go:276") + CallerTestErrorf = path.Join(SourceDir, "context.go:374") // CallerReporterErrorf provides the file with the line number of the // `Errorf` call in the test reporter/validator implementation. - CallerReporterErrorf = path.Join(SourceDir, "gomock.go:61") + CallerReporterErrorf = path.Join(SourceDir, "gomock.go:82") ) diff --git a/test/common_test.go b/test/common_test.go index 5384715..8b8fa46 100644 --- a/test/common_test.go +++ b/test/common_test.go @@ -3,6 +3,7 @@ package test_test import ( "regexp" + "github.com/stretchr/testify/assert" "github.com/tkrop/go-testing/internal/sync" "github.com/tkrop/go-testing/mock" "github.com/tkrop/go-testing/test" @@ -58,14 +59,39 @@ func (m TestParamMap) GetSlice() []TestParam { var ( // TestEmpty is a test function that does nothing. TestEmpty = func(test.Test) {} - // TestErrorf is a test function that fails with an error message. + // TestSkip is a test function that skips the test. + TestSkip = func(t test.Test) { t.Skip("skip") } + // TestSkipf is a test function that skips the test with a formatted message. + TestSkipf = func(t test.Test) { t.Skipf("skip") } + // TestSkipNow is a test function that skips the test immediately. + TestSkipNow = func(t test.Test) { t.SkipNow() } + // TestLog is a test function that logs a message. + TestLog = func(t test.Test) { t.Log("log") } + // TestLogf is a test function that logs a formatted message. + TestLogf = func(t test.Test) { t.Logf("log") } + // TestError is a test function that fails with an error message. + TestError = func(t test.Test) { t.Error("fail") } + // TestErrorf is a test function that fails with a formatted error message. TestErrorf = func(t test.Test) { t.Errorf("fail") } - // TestFatalf is a test function that fails with a fatal error message. + // TestFatal is a test function that fails with a fatal error message. + TestFatal = func(t test.Test) { + // Duplicate terminal failures are ignored. + go func() { t.Fatal("fail") }() + t.Fatal("fail") + } + // TestFatalf is a test function that fails with a fatal formatted error + // message. TestFatalf = func(t test.Test) { // Duplicate terminal failures are ignored. go func() { t.Fatalf("fail") }() t.Fatalf("fail") } + // TestFail is a test function that fails. + TestFail = func(t test.Test) { + // Duplicate terminal failures are ignored. + go func() { t.Fail() }() + t.Fail() + } // TestFailNow is a test function that fails immediately. TestFailNow = func(t test.Test) { // Duplicate terminal failures are ignored. @@ -87,15 +113,49 @@ var testParams = TestParamMap{ test: TestEmpty, expect: test.Success, }, + "base skip": { + test: TestSkip, + expect: test.Success, + }, + "base skipf": { + test: TestSkipf, + expect: test.Success, + }, + "base skipnow": { + test: TestSkipNow, + expect: test.Success, + }, + "base log": { + test: TestLog, + expect: test.Success, + }, + "base logf": { + test: TestLogf, + expect: test.Success, + }, + "base error": { + test: TestError, + expect: test.Failure, + }, "base errorf": { test: TestErrorf, expect: test.Failure, }, + "base fatal": { + test: TestFatal, + expect: test.Failure, + consumed: true, + }, "base fatalf": { test: TestFatalf, expect: test.Failure, consumed: true, }, + "base fail": { + test: TestFail, + expect: test.Failure, + consumed: true, + }, "base failnow": { test: TestFailNow, expect: test.Failure, @@ -111,15 +171,49 @@ var testParams = TestParamMap{ test: test.InRun(test.Success, TestEmpty), expect: test.Success, }, + "inrun success with skip": { + test: test.InRun(test.Success, TestSkip), + expect: test.Success, + }, + "inrun success with skipf": { + test: test.InRun(test.Success, TestSkipf), + expect: test.Success, + }, + "inrun success with skipnow": { + test: test.InRun(test.Success, TestSkipNow), + expect: test.Success, + }, + "inrun success with log": { + test: test.InRun(test.Success, TestLog), + expect: test.Success, + }, + "inrun success with logf": { + test: test.InRun(test.Success, TestLogf), + expect: test.Success, + }, + "inrun success with error": { + test: test.InRun(test.Success, TestError), + expect: test.Failure, + }, "inrun success with errorf": { test: test.InRun(test.Success, TestErrorf), expect: test.Failure, }, + "inrun success with fatal": { + test: test.InRun(test.Success, TestFatal), + expect: test.Failure, + consumed: true, + }, "inrun success with fatalf": { test: test.InRun(test.Success, TestFatalf), expect: test.Failure, consumed: true, }, + "inrun success with fail": { + test: test.InRun(test.Success, TestFail), + expect: test.Failure, + consumed: true, + }, "inrun success with failnow": { test: test.InRun(test.Success, TestFailNow), expect: test.Failure, @@ -135,15 +229,49 @@ var testParams = TestParamMap{ test: test.InRun(test.Failure, TestEmpty), expect: test.Failure, }, + "inrun failure with skip": { + test: test.InRun(test.Failure, TestSkip), + expect: test.Failure, + }, + "inrun failure with skipf": { + test: test.InRun(test.Failure, TestSkipf), + expect: test.Failure, + }, + "inrun failure with skipnow": { + test: test.InRun(test.Failure, TestSkipNow), + expect: test.Failure, + }, + "inrun failure with log": { + test: test.InRun(test.Failure, TestLog), + expect: test.Failure, + }, + "inrun failure with logf": { + test: test.InRun(test.Failure, TestLogf), + expect: test.Failure, + }, + "inrun failure with error": { + test: test.InRun(test.Failure, TestError), + expect: test.Success, + }, "inrun failure with errorf": { test: test.InRun(test.Failure, TestErrorf), expect: test.Success, }, + "inrun failure with fatal": { + test: test.InRun(test.Failure, TestFatal), + expect: test.Success, + consumed: true, + }, "inrun failure with fatalf": { test: test.InRun(test.Failure, TestFatalf), expect: test.Success, consumed: true, }, + "inrun failure with fail": { + test: test.InRun(test.Failure, TestFail), + expect: test.Success, + consumed: true, + }, "inrun failure with failnow": { test: test.InRun(test.Failure, TestFailNow), expect: test.Success, @@ -175,4 +303,7 @@ func ExecTest(t test.Test, param TestParam) { // Then wg.Wait() + if param.expect == test.Failure { + assert.True(t, t.Failed()) + } } diff --git a/test/context.go b/test/context.go index 8edd032..df6d17c 100644 --- a/test/context.go +++ b/test/context.go @@ -16,7 +16,7 @@ import ( // Test is a minimal interface for abstracting test methods that are needed to // setup an isolated test environment for GoMock and Testify. -type Test interface { +type Test interface { //nolint:interfacebloat // Minimal interface. // Name provides the test name. Name() string // Helper declares a test helper function. @@ -31,29 +31,61 @@ type Test interface { // Deadline returns the deadline of the test and a flag indicating whether // the deadline is set. Deadline() (deadline time.Time, ok bool) + // Skip is a helper method to skip the test. + Skip(args ...any) + // Skipf is a helper method to skip the test with a formatted message. + Skipf(format string, args ...any) + // SkipNow is a helper method to skip the test immediately. + SkipNow() + // Skipped reports whether the test has been skipped. + Skipped() bool + // Log provides a logging function for the test. + Log(args ...any) + // Logf provides a logging function for the test. + Logf(format string, args ...any) + // Error handles a failure messages when a test is supposed to continue. + Error(args ...any) // Errorf handles a failure messages when a test is supposed to continue. Errorf(format string, args ...any) + // Fatal handles a fatal failure message that immediate aborts of the test + // execution. + Fatal(args ...any) // Fatalf handles a fatal failure message that immediate aborts of the test // execution. Fatalf(format string, args ...any) + // Fail handles a failure message that immediate aborts of the test + // execution. + Fail() // FailNow handles fatal failure notifications without log output that // aborts test execution immediately. FailNow() + // Failed reports whether the test has failed. + Failed() bool + // Cleanup is a function called to setup test cleanup after execution. + Cleanup(cleanup func()) } // Reporter is a minimal interface for abstracting test report methods that are // needed to setup an isolated test environment for GoMock and Testify. type Reporter interface { - // Panic reports a panic. - Panic(arg any) + // Error reports a failure messages when a test is supposed to continue. + Error(args ...any) // Errorf reports a failure messages when a test is supposed to continue. Errorf(format string, args ...any) + // Fatal reports a fatal failure message that immediate aborts of the test + // execution. + Fatal(args ...any) // Fatalf reports a fatal failure message that immediate aborts of the test // execution. Fatalf(format string, args ...any) + // Fail reports a failure message that immediate aborts of the test + // execution. + Fail() // FailNow reports fatal failure notifications without log output that // aborts test execution immediately. FailNow() + // Panic reports a panic. + Panic(arg any) } // Cleanuper defines an interface to add a custom mehtod that is called after @@ -235,7 +267,6 @@ func (t *Context) Parallel() { // TempDir delegates the request to the parent test context. func (t *Context) TempDir() string { t.t.Helper() - return t.t.TempDir() } @@ -243,6 +274,7 @@ func (t *Context) TempDir() string { // `*testing.T`. Else it is swallowing the request silently. func (t *Context) Setenv(key, value string) { t.t.Helper() + t.t.Setenv(key, value) } @@ -259,6 +291,72 @@ func (t *Context) Deadline() (time.Time, bool) { return t.t.Deadline() } +// Skip delegates request to the parent context. It is a helper method to skip +// the test. +func (t *Context) Skip(args ...any) { + t.t.Helper() + + t.t.Skip(args...) +} + +// Skipf delegates request to the parent context. It is a helper method to skip +// the test with a formatted message. +func (t *Context) Skipf(format string, args ...any) { + t.t.Helper() + + t.t.Skipf(format, args...) +} + +// SkipNow delegates request to the parent context. It is a helper method to skip +// the test immediately. +func (t *Context) SkipNow() { + t.t.Helper() + + t.t.SkipNow() +} + +// Skipped delegates request to the parent context. It reports whether the test +// has been skipped. +func (t *Context) Skipped() bool { + t.t.Helper() + + return t.t.Skipped() +} + +// Log delegates request to the parent context. It provides a logging function +// for the test. +func (t *Context) Log(args ...any) { + t.t.Helper() + + t.t.Log(args...) +} + +// Logf delegates request to the parent context. It provides a logging function +// for the test. +func (t *Context) Logf(format string, args ...any) { + t.t.Helper() + + t.t.Logf(format, args...) +} + +// Error handles failure messages where the test is supposed to continue. On +// an expected success, the failure is also delegated to the parent test +// context. Else it delegates the request to the test reporter if available. +func (t *Context) Error(args ...any) { + t.t.Helper() + + t.failed.Store(true) + + t.mu.Lock() + defer t.mu.Unlock() + + if t.expect == Success { + t.t.Error(args...) + } else if t.reporter != nil { + t.reporter.Error(args...) + } +} + // Errorf handles failure messages where the test is supposed to continue. On // an expected success, the failure is also delegated to the parent test // context. Else it delegates the request to the test reporter if available. @@ -277,6 +375,29 @@ func (t *Context) Errorf(format string, args ...any) { } } +// Fatal handles a fatal failure message that immediate aborts of the test +// execution. On an expected success, the failure handling is also delegated +// to the parent test context. Else it delegates the request to the test +// reporter if available. +func (t *Context) Fatal(args ...any) { + t.t.Helper() + + if t.failed.Swap(true) { + runtime.Goexit() + } + + t.mu.Lock() + defer t.mu.Unlock() + defer t.unlock() + + if t.expect == Success { + t.t.Fatal(args...) + } else if t.reporter != nil { + t.reporter.Fatal(args...) + } + runtime.Goexit() +} + // Fatalf handles a fatal failure message that immediate aborts of the test // execution. On an expected success, the failure handling is also delegated // to the parent test context. Else it delegates the request to the test @@ -300,6 +421,28 @@ func (t *Context) Fatalf(format string, args ...any) { runtime.Goexit() } +// Fail handles a failure message that immediate aborts of the test execution. +// On an expected success, the failure handling is also delegated to the parent +// test context. Else it delegates the request to the test reporter if available. +func (t *Context) Fail() { + t.t.Helper() + + if t.failed.Swap(true) { + runtime.Goexit() + } + + t.mu.Lock() + defer t.mu.Unlock() + defer t.unlock() + + if t.expect == Success { + t.t.Fail() + } else if t.reporter != nil { + t.reporter.Fail() + } + runtime.Goexit() +} + // FailNow handles fatal failure notifications without log output that aborts // test execution immediately. On an expected success, it the failure handling // is also delegated to the parent test context. Else it delegates the request @@ -323,6 +466,13 @@ func (t *Context) FailNow() { runtime.Goexit() } +// Failed reports whether the test has failed. +func (t *Context) Failed() bool { + t.t.Helper() + + return t.failed.Load() +} + // Offset fr original stack in case of panic handling. // // TODO: check offset or/and find a better solution to handle panic stack. @@ -442,6 +592,10 @@ func (t *Context) finish() { t.mu.Lock() defer t.mu.Unlock() + if t.t.Skipped() { + return + } + switch t.expect { case Success: if t.failed.Load() { diff --git a/test/gomock.go b/test/gomock.go index c981893..0ffd280 100644 --- a/test/gomock.go +++ b/test/gomock.go @@ -40,6 +40,27 @@ func (v *Validator) EXPECT() *Recorder { return v.recorder } +// Error receive expected method call to `Error`. +func (v *Validator) Error(args ...any) { + v.ctrl.T.Helper() + v.ctrl.Call(v, "Error", args...) +} + +// Error indicate an expected method call to `Error`. +func (r *Recorder) Error(args ...any) *gomock.Call { + r.validator.ctrl.T.Helper() + return r.validator.ctrl.RecordCallWithMethodType(r.validator, "Error", + reflect.TypeOf((*Validator)(nil).Error), args...) +} + +// Error creates a validation method call setup for `Error`. +func Error(args ...any) mock.SetupFunc { + return func(mocks *mock.Mocks) any { + return mock.Get(mocks, NewValidator).EXPECT(). + Error(args...).Do(mocks.Do(Reporter.Error)) + } +} + // Errorf receive expected method call to `Errorf`. func (v *Validator) Errorf(format string, args ...any) { v.ctrl.T.Helper() @@ -62,6 +83,27 @@ func Errorf(format string, args ...any) mock.SetupFunc { } } +// Fatal receive expected method call to `Fatal`. +func (v *Validator) Fatal(args ...any) { + v.ctrl.T.Helper() + v.ctrl.Call(v, "Fatal", args...) +} + +// Fatal indicate an expected method call to `Fatal`. +func (r *Recorder) Fatal(args ...any) *gomock.Call { + r.validator.ctrl.T.Helper() + return r.validator.ctrl.RecordCallWithMethodType(r.validator, "Fatal", + reflect.TypeOf((*Validator)(nil).Fatal), args...) +} + +// Fatal creates a validation method call setup for `Fatal`. +func Fatal(args ...any) mock.SetupFunc { + return func(mocks *mock.Mocks) any { + return mock.Get(mocks, NewValidator).EXPECT(). + Fatal(args...).Do(mocks.Do(Reporter.Fatal)) + } +} + // Fatalf receive expected method call to `Fatalf`. func (v *Validator) Fatalf(format string, args ...any) { v.ctrl.T.Helper() @@ -84,6 +126,27 @@ func Fatalf(format string, args ...any) mock.SetupFunc { } } +// Fail receive expected method call to `Fail`. +func (v *Validator) Fail() { + v.ctrl.T.Helper() + v.ctrl.Call(v, "Fail") +} + +// Fail indicate an expected method call to `Fail`. +func (r *Recorder) Fail() *gomock.Call { + r.validator.ctrl.T.Helper() + return r.validator.ctrl.RecordCallWithMethodType(r.validator, "Fail", + reflect.TypeOf((*Validator)(nil).Fail)) +} + +// Fail creates a validation method call setup for `Fail`. +func Fail() mock.SetupFunc { + return func(mocks *mock.Mocks) any { + return mock.Get(mocks, NewValidator).EXPECT(). + Fail().Do(mocks.Do(Reporter.Fail)) + } +} + // FailNow receive expected method call to `FailNow`. func (v *Validator) FailNow() { v.ctrl.T.Helper() diff --git a/test/gomock_test.go b/test/gomock_test.go index 119f89d..c422313 100644 --- a/test/gomock_test.go +++ b/test/gomock_test.go @@ -167,18 +167,36 @@ type ReporterParams struct { } var testReporterParams = map[string]ReporterParams{ + "error called": { + mockSetup: test.Error("fail"), + call: func(t test.Test) { + t.Error("fail") + }, + }, "errorf called": { mockSetup: test.Errorf("fail"), call: func(t test.Test) { t.Errorf("fail") }, }, + "fatal called": { + mockSetup: test.Fatal("fail"), + call: func(t test.Test) { + t.Fatal("fail") + }, + }, "fatalf called": { mockSetup: test.Fatalf("fail"), call: func(t test.Test) { t.Fatalf("fail") }, }, + "fail called": { + mockSetup: test.Fail(), + call: func(t test.Test) { + t.Fail() + }, + }, "failnow called": { mockSetup: test.FailNow(), call: func(t test.Test) { @@ -192,6 +210,21 @@ var testReporterParams = map[string]ReporterParams{ }, }, + "error undeclared": { + failSetup: test.UnexpectedCall(test.NewValidator, + "Error", CallerError, "fail"), + call: func(t test.Test) { + t.Error("fail") + }, + }, + "error undeclared twice": { + failSetup: test.UnexpectedCall(test.NewValidator, + "Error", CallerError, "fail"), + call: func(t test.Test) { + t.Error("fail") + t.Error("fail") + }, + }, "errorf undeclared": { failSetup: test.UnexpectedCall(test.NewValidator, "Errorf", CallerErrorf, "fail"), @@ -207,6 +240,22 @@ var testReporterParams = map[string]ReporterParams{ t.Errorf("fail") }, }, + "fatal undeclared": { + failSetup: test.UnexpectedCall(test.NewValidator, + "Fatal", CallerFatal, "fail"), + call: func(t test.Test) { + t.Fatal("fail") + }, + }, + "fatal undeclared twice": { + failSetup: test.UnexpectedCall(test.NewValidator, + "Fatal", CallerFatal, "fail"), + call: func(t test.Test) { + //revive:disable-next-line:unreachable-code // needed for testing + t.Fatal("fail") + t.Fatal("fail") + }, + }, "fatalf undeclared": { failSetup: test.UnexpectedCall(test.NewValidator, "Fatalf", CallerFatalf, "fail"), @@ -214,6 +263,15 @@ var testReporterParams = map[string]ReporterParams{ t.Fatalf("fail") }, }, + "fatalf undeclared twice": { + failSetup: test.UnexpectedCall(test.NewValidator, + "Fatalf", CallerFatalf, "fail"), + call: func(t test.Test) { + //revive:disable-next-line:unreachable-code // needed for testing + t.Fatalf("fail") + t.Fatalf("fail") + }, + }, "failnow undeclared": { failSetup: test.UnexpectedCall(test.NewValidator, "FailNow", CallerFailNow), @@ -221,6 +279,15 @@ var testReporterParams = map[string]ReporterParams{ t.FailNow() }, }, + "failnow undeclared twice": { + failSetup: test.UnexpectedCall(test.NewValidator, + "FailNow", CallerFailNow), + call: func(t test.Test) { + //revive:disable-next-line:unreachable-code // needed for testing + t.FailNow() + t.FailNow() + }, + }, "panic undeclared": { failSetup: test.UnexpectedCall(test.NewValidator, "Panic", CallerPanic, "fail"), @@ -229,9 +296,18 @@ var testReporterParams = map[string]ReporterParams{ }, }, - // Only Errorf can be consumed more than once, since Fatalf, FailNow, and - // panic will stop execution immediately. The second call is effectively - // unreachable. + // Only `Error`and `Errorf` can be consumed more than once, since `Fatal`, + // `Fatalf`, `FailNow`, and panic will stop execution immediately. The + // second call is effectively unreachable. + "error consumed": { + mockSetup: test.Error("fail"), + failSetup: test.ConsumedCall(test.NewValidator, + "Error", CallerTestError, CallerReporterError, "fail"), + call: func(t test.Test) { + t.Error("fail") + t.Error("fail") + }, + }, "errorf consumed": { mockSetup: test.Errorf("fail"), failSetup: test.ConsumedCall(test.NewValidator, @@ -241,6 +317,14 @@ var testReporterParams = map[string]ReporterParams{ t.Errorf("fail") }, }, + "fatal consumed": { + mockSetup: test.Fatal("fail"), + call: func(t test.Test) { + //revive:disable-next-line:unreachable-code // needed for testing + t.Fatal("fail") + t.Fatal("fail") + }, + }, "fatalf consumed": { mockSetup: test.Fatalf("fail"), call: func(t test.Test) { @@ -294,6 +378,13 @@ var testReporterParams = map[string]ReporterParams{ t.Errorf("fail") }, }, + "fail missing": { + mockSetup: mock.Chain(test.Errorf("fail"), test.Fail()), + failSetup: test.MissingCalls(test.Fail()), + call: func(t test.Test) { + t.Errorf("fail") + }, + }, "failnow missing": { mockSetup: mock.Chain(test.Errorf("fail"), test.FailNow()), failSetup: test.MissingCalls(test.FailNow()),