From d63d67edd467db8e2777c71c02455bfa72e6a72e Mon Sep 17 00:00:00 2001 From: Onsi Fakhouri Date: Wed, 26 Oct 2022 06:15:15 -0600 Subject: [PATCH] Rename AsyncSignalError to PollingSignalError ...and use it everywhere --- gomega_dsl.go | 5 + internal/async_assertion.go | 23 ++-- internal/async_assertion_test.go | 1 - internal/async_signal_error.go | 107 ------------------ internal/polling_signal_error.go | 106 +++++++++++++++++ ...r_test.go => polling_signal_error_test.go} | 20 ++-- 6 files changed, 132 insertions(+), 130 deletions(-) delete mode 100644 internal/async_signal_error.go create mode 100644 internal/polling_signal_error.go rename internal/{async_signal_error_test.go => polling_signal_error_test.go} (68%) diff --git a/gomega_dsl.go b/gomega_dsl.go index 8c49e3e98..2208a37ed 100644 --- a/gomega_dsl.go +++ b/gomega_dsl.go @@ -443,6 +443,11 @@ When `TryAgainAfter(` is triggered `Eventually` and `Consistently` wil */ var TryAgainAfter = internal.TryAgainAfter +/* +PollingSignalError is the error returned by StopTrying() and TryAgainAfter() +*/ +type PollingSignalError = internal.PollingSignalError + // SetDefaultEventuallyTimeout sets the default timeout duration for Eventually. Eventually will repeatedly poll your condition until it succeeds, or until this timeout elapses. func SetDefaultEventuallyTimeout(t time.Duration) { Default.SetDefaultEventuallyTimeout(t) diff --git a/internal/async_assertion.go b/internal/async_assertion.go index 946fc6b9b..044acc761 100644 --- a/internal/async_assertion.go +++ b/internal/async_assertion.go @@ -134,7 +134,7 @@ func (assertion *AsyncAssertion) processReturnValues(values []reflect.Value) (in } actual := values[0].Interface() - if _, ok := AsAsyncSignalError(actual); ok { + if _, ok := AsPollingSignalError(actual); ok { return actual, actual.(error) } @@ -144,7 +144,7 @@ func (assertion *AsyncAssertion) processReturnValues(values []reflect.Value) (in if extra == nil { continue } - if _, ok := AsAsyncSignalError(extra); ok { + if _, ok := AsPollingSignalError(extra); ok { return actual, extra.(error) } extraType := reflect.TypeOf(extra) @@ -253,13 +253,13 @@ func (assertion *AsyncAssertion) buildActualPoller() (func() (interface{}, error actual = assertionFailure } else { actual, err = assertion.processReturnValues(values) - _, isAsyncError := AsAsyncSignalError(err) + _, isAsyncError := AsPollingSignalError(err) if assertionFailure != nil && !isAsyncError { err = assertionFailure } } if e := recover(); e != nil { - if _, isAsyncError := AsAsyncSignalError(e); isAsyncError { + if _, isAsyncError := AsPollingSignalError(e); isAsyncError { err = e.(error) } else if assertionFailure == nil { panic(e) @@ -308,7 +308,7 @@ func (assertion *AsyncAssertion) matcherSaysStopTrying(matcher types.GomegaMatch func (assertion *AsyncAssertion) pollMatcher(matcher types.GomegaMatcher, value interface{}) (matches bool, err error) { defer func() { if e := recover(); e != nil { - if _, isAsyncError := AsAsyncSignalError(e); isAsyncError { + if _, isAsyncError := AsPollingSignalError(e); isAsyncError { err = e.(error) } else { panic(e) @@ -350,10 +350,9 @@ func (assertion *AsyncAssertion) match(matcher types.GomegaMatcher, desiredMatch defer lock.Unlock() message := "" if err != nil { - //TODO - formatting for TryAgainAfter? - if asyncSignal, ok := AsAsyncSignalError(err); ok && asyncSignal.IsStopTrying() { + if pollingSignalErr, ok := AsPollingSignalError(err); ok && pollingSignalErr.IsStopTrying() { message = err.Error() - for _, attachment := range asyncSignal.Attachments { + for _, attachment := range pollingSignalErr.Attachments { message += fmt.Sprintf("\n%s:\n", attachment.Description) message += format.Object(attachment.Object, 1) } @@ -389,13 +388,13 @@ func (assertion *AsyncAssertion) match(matcher types.GomegaMatcher, desiredMatch var nextPoll <-chan time.Time = nil var isTryAgainAfterError = false - if asyncSignal, ok := AsAsyncSignalError(err); ok { - if asyncSignal.IsStopTrying() { + if pollingSignalErr, ok := AsPollingSignalError(err); ok { + if pollingSignalErr.IsStopTrying() { fail("Told to stop trying") return false } - if asyncSignal.IsTryAgainAfter() { - nextPoll = time.After(asyncSignal.TryAgainDuration()) + if pollingSignalErr.IsTryAgainAfter() { + nextPoll = time.After(pollingSignalErr.TryAgainDuration()) isTryAgainAfterError = true } } diff --git a/internal/async_assertion_test.go b/internal/async_assertion_test.go index fe3cfc642..338eb2ae3 100644 --- a/internal/async_assertion_test.go +++ b/internal/async_assertion_test.go @@ -1448,7 +1448,6 @@ sprocket: ig.G.Eventually(42).Should(HaveLen(1), "foo", ContainElement(42)) }).NotTo(Panic()) }) - }) Context("eventual nil-ism", func() { // issue #555 diff --git a/internal/async_signal_error.go b/internal/async_signal_error.go deleted file mode 100644 index 8c71e7f7a..000000000 --- a/internal/async_signal_error.go +++ /dev/null @@ -1,107 +0,0 @@ -package internal - -import ( - "errors" - "time" - "fmt" -) - -type AsyncSignalErrorType int - -const ( - AsyncSignalErrorTypeStopTrying AsyncSignalErrorType = iota - AsyncSignalErrorTypeTryAgainAfter -) - -type AsyncSignalError interface { - error - Wrap(err error) AsyncSignalError - Attach(description string, obj any) AsyncSignalError - Now() -} - - -var StopTrying = func(message string) AsyncSignalError { - return &AsyncSignalErrorImpl{ - message: message, - asyncSignalErrorType: AsyncSignalErrorTypeStopTrying, - } -} - -var TryAgainAfter = func(duration time.Duration) AsyncSignalError { - return &AsyncSignalErrorImpl{ - message: fmt.Sprintf("told to try again after %s", duration), - duration: duration, - asyncSignalErrorType: AsyncSignalErrorTypeTryAgainAfter, - } -} - -type AsyncSignalErrorAttachment struct { - Description string - Object any -} - -type AsyncSignalErrorImpl struct { - message string - wrappedErr error - asyncSignalErrorType AsyncSignalErrorType - duration time.Duration - Attachments []AsyncSignalErrorAttachment -} - -func (s *AsyncSignalErrorImpl) Wrap(err error) AsyncSignalError { - s.wrappedErr = err - return s -} - -func (s *AsyncSignalErrorImpl) Attach(description string, obj any) AsyncSignalError { - s.Attachments = append(s.Attachments, AsyncSignalErrorAttachment{description, obj}) - return s -} - -func (s *AsyncSignalErrorImpl) Error() string { - if s.wrappedErr == nil { - return s.message - } else { - return s.message + ": " + s.wrappedErr.Error() - } -} - -func (s *AsyncSignalErrorImpl) Unwrap() error { - if s == nil { - return nil - } - return s.wrappedErr -} - -func (s *AsyncSignalErrorImpl) Now() { - panic(s) -} - -func (s *AsyncSignalErrorImpl) IsStopTrying() bool { - return s.asyncSignalErrorType == AsyncSignalErrorTypeStopTrying -} - -func (s *AsyncSignalErrorImpl) IsTryAgainAfter() bool { - return s.asyncSignalErrorType == AsyncSignalErrorTypeTryAgainAfter -} - -func (s *AsyncSignalErrorImpl) TryAgainDuration() time.Duration { - return s.duration -} - -func AsAsyncSignalError(actual interface{}) (*AsyncSignalErrorImpl, bool) { - if actual == nil { - return nil, false - } - if actualErr, ok := actual.(error); ok { - var target *AsyncSignalErrorImpl - if errors.As(actualErr, &target) { - return target, true - } else { - return nil, false - } - } - - return nil, false -} diff --git a/internal/polling_signal_error.go b/internal/polling_signal_error.go new file mode 100644 index 000000000..83b04b1a4 --- /dev/null +++ b/internal/polling_signal_error.go @@ -0,0 +1,106 @@ +package internal + +import ( + "errors" + "fmt" + "time" +) + +type PollingSignalErrorType int + +const ( + PollingSignalErrorTypeStopTrying PollingSignalErrorType = iota + PollingSignalErrorTypeTryAgainAfter +) + +type PollingSignalError interface { + error + Wrap(err error) PollingSignalError + Attach(description string, obj any) PollingSignalError + Now() +} + +var StopTrying = func(message string) PollingSignalError { + return &PollingSignalErrorImpl{ + message: message, + pollingSignalErrorType: PollingSignalErrorTypeStopTrying, + } +} + +var TryAgainAfter = func(duration time.Duration) PollingSignalError { + return &PollingSignalErrorImpl{ + message: fmt.Sprintf("told to try again after %s", duration), + duration: duration, + pollingSignalErrorType: PollingSignalErrorTypeTryAgainAfter, + } +} + +type PollingSignalErrorAttachment struct { + Description string + Object any +} + +type PollingSignalErrorImpl struct { + message string + wrappedErr error + pollingSignalErrorType PollingSignalErrorType + duration time.Duration + Attachments []PollingSignalErrorAttachment +} + +func (s *PollingSignalErrorImpl) Wrap(err error) PollingSignalError { + s.wrappedErr = err + return s +} + +func (s *PollingSignalErrorImpl) Attach(description string, obj any) PollingSignalError { + s.Attachments = append(s.Attachments, PollingSignalErrorAttachment{description, obj}) + return s +} + +func (s *PollingSignalErrorImpl) Error() string { + if s.wrappedErr == nil { + return s.message + } else { + return s.message + ": " + s.wrappedErr.Error() + } +} + +func (s *PollingSignalErrorImpl) Unwrap() error { + if s == nil { + return nil + } + return s.wrappedErr +} + +func (s *PollingSignalErrorImpl) Now() { + panic(s) +} + +func (s *PollingSignalErrorImpl) IsStopTrying() bool { + return s.pollingSignalErrorType == PollingSignalErrorTypeStopTrying +} + +func (s *PollingSignalErrorImpl) IsTryAgainAfter() bool { + return s.pollingSignalErrorType == PollingSignalErrorTypeTryAgainAfter +} + +func (s *PollingSignalErrorImpl) TryAgainDuration() time.Duration { + return s.duration +} + +func AsPollingSignalError(actual interface{}) (*PollingSignalErrorImpl, bool) { + if actual == nil { + return nil, false + } + if actualErr, ok := actual.(error); ok { + var target *PollingSignalErrorImpl + if errors.As(actualErr, &target) { + return target, true + } else { + return nil, false + } + } + + return nil, false +} diff --git a/internal/async_signal_error_test.go b/internal/polling_signal_error_test.go similarity index 68% rename from internal/async_signal_error_test.go rename to internal/polling_signal_error_test.go index 2207e9b40..564ef750b 100644 --- a/internal/async_signal_error_test.go +++ b/internal/polling_signal_error_test.go @@ -9,14 +9,14 @@ import ( "github.com/onsi/gomega/internal" ) -var _ = Describe("AsyncSignalError", func() { +var _ = Describe("PollingSignalError", func() { Describe("StopTrying", func() { Describe("building StopTrying errors", func() { It("returns a correctly configured StopTrying error", func() { st := StopTrying("I've tried 17 times - give up!") Ω(st.Error()).Should(Equal("I've tried 17 times - give up!")) Ω(errors.Unwrap(st)).Should(BeNil()) - Ω(st.(*internal.AsyncSignalErrorImpl).IsStopTrying()).Should(BeTrue()) + Ω(st.(*internal.PollingSignalErrorImpl).IsStopTrying()).Should(BeTrue()) }) }) @@ -32,35 +32,35 @@ var _ = Describe("AsyncSignalError", func() { Describe("When attaching objects", func() { It("attaches them, with their descriptions", func() { - st := StopTrying("Welp!").Attach("Max retries attained", 17).Attach("Got this response", "FLOOP").(*internal.AsyncSignalErrorImpl) + st := StopTrying("Welp!").Attach("Max retries attained", 17).Attach("Got this response", "FLOOP").(*internal.PollingSignalErrorImpl) Ω(st.Attachments).Should(HaveLen(2)) - Ω(st.Attachments[0]).Should(Equal(internal.AsyncSignalErrorAttachment{"Max retries attained", 17})) - Ω(st.Attachments[1]).Should(Equal(internal.AsyncSignalErrorAttachment{"Got this response", "FLOOP"})) + Ω(st.Attachments[0]).Should(Equal(internal.PollingSignalErrorAttachment{"Max retries attained", 17})) + Ω(st.Attachments[1]).Should(Equal(internal.PollingSignalErrorAttachment{"Got this response", "FLOOP"})) }) }) Describe("when invoking Now()", func() { It("should panic with itself", func() { - st := StopTrying("bam").(*internal.AsyncSignalErrorImpl) + st := StopTrying("bam").(*internal.PollingSignalErrorImpl) Ω(st.Now).Should(PanicWith(st)) }) }) - Describe("AsAsyncSignalError", func() { + Describe("AsPollingSignalError", func() { It("should return false for nils", func() { - st, ok := internal.AsAsyncSignalError(nil) + st, ok := internal.AsPollingSignalError(nil) Ω(st).Should(BeNil()) Ω(ok).Should(BeFalse()) }) It("should work when passed a StopTrying error", func() { - st, ok := internal.AsAsyncSignalError(StopTrying("bam")) + st, ok := internal.AsPollingSignalError(StopTrying("bam")) Ω(st).Should(Equal(StopTrying("bam"))) Ω(ok).Should(BeTrue()) }) It("should work when passed a wrapped error", func() { - st, ok := internal.AsAsyncSignalError(fmt.Errorf("STOP TRYING %w", StopTrying("bam"))) + st, ok := internal.AsPollingSignalError(fmt.Errorf("STOP TRYING %w", StopTrying("bam"))) Ω(st).Should(Equal(StopTrying("bam"))) Ω(ok).Should(BeTrue()) })