174 lines
6.5 KiB
Go
174 lines
6.5 KiB
Go
package failures_test
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/onsi/ginkgo/v2"
|
|
"github.com/onsi/gomega"
|
|
"github.com/onsi/gomega/format"
|
|
|
|
"github.com/nicholas-fedor/shoutrrr/internal/failures"
|
|
"github.com/nicholas-fedor/shoutrrr/internal/testutils"
|
|
)
|
|
|
|
// TestFailures runs the Ginkgo test suite for the failures package.
|
|
func TestFailures(t *testing.T) {
|
|
format.CharactersAroundMismatchToInclude = 20 // Show more context in failure output
|
|
|
|
gomega.RegisterFailHandler(ginkgo.Fail)
|
|
ginkgo.RunSpecs(t, "Failure Suite")
|
|
}
|
|
|
|
var _ = ginkgo.Describe("the failure package", func() {
|
|
// Common test fixtures
|
|
var (
|
|
testID failures.FailureID = 42 // Consistent ID for testing
|
|
testMessage = "test failure occurred" // Sample error message
|
|
wrappedErr = errors.New("underlying error") // Sample wrapped error
|
|
)
|
|
|
|
ginkgo.Describe("Wrap function", func() {
|
|
ginkgo.When("creating a basic failure", func() {
|
|
ginkgo.It("returns a failure with the provided message and ID", func() {
|
|
failure := failures.Wrap(testMessage, testID, nil)
|
|
gomega.Expect(failure.Error()).To(gomega.Equal(testMessage))
|
|
gomega.Expect(failure.ID()).To(gomega.Equal(testID))
|
|
gomega.Expect(failure.Unwrap()).To(gomega.Succeed())
|
|
})
|
|
})
|
|
|
|
ginkgo.When("wrapping an existing error", func() {
|
|
ginkgo.It("combines the message and wrapped error", func() {
|
|
failure := failures.Wrap(testMessage, testID, wrappedErr)
|
|
expectedError := fmt.Sprintf("%s: %v", testMessage, wrappedErr)
|
|
gomega.Expect(failure.Error()).To(gomega.Equal(expectedError))
|
|
gomega.Expect(failure.ID()).To(gomega.Equal(testID))
|
|
gomega.Expect(failure.Unwrap()).To(gomega.Equal(wrappedErr))
|
|
})
|
|
})
|
|
|
|
ginkgo.When("using formatted message with arguments", func() {
|
|
ginkgo.It("formats the message correctly", func() {
|
|
formatMessage := "test failure %d"
|
|
failure := failures.Wrap(formatMessage, testID, nil, 123)
|
|
gomega.Expect(failure.Error()).To(gomega.Equal("test failure 123"))
|
|
gomega.Expect(failure.ID()).To(gomega.Equal(testID))
|
|
})
|
|
})
|
|
})
|
|
|
|
ginkgo.Describe("Failure interface methods", func() {
|
|
var failure failures.Failure
|
|
|
|
// Setup a failure with a wrapped error before each test
|
|
ginkgo.BeforeEach(func() {
|
|
failure = failures.Wrap(testMessage, testID, wrappedErr)
|
|
})
|
|
|
|
ginkgo.Describe("Error method", func() {
|
|
ginkgo.It("returns only the message when no wrapped error exists", func() {
|
|
failureNoWrap := failures.Wrap(testMessage, testID, nil)
|
|
gomega.Expect(failureNoWrap.Error()).To(gomega.Equal(testMessage))
|
|
})
|
|
ginkgo.It("combines message with wrapped error", func() {
|
|
expected := fmt.Sprintf("%s: %v", testMessage, wrappedErr)
|
|
gomega.Expect(failure.Error()).To(gomega.Equal(expected))
|
|
})
|
|
})
|
|
|
|
ginkgo.Describe("ID method", func() {
|
|
ginkgo.It("returns the assigned ID", func() {
|
|
gomega.Expect(failure.ID()).To(gomega.Equal(testID))
|
|
})
|
|
})
|
|
|
|
ginkgo.Describe("Unwrap method", func() {
|
|
ginkgo.It("returns the wrapped error", func() {
|
|
gomega.Expect(failure.Unwrap()).To(gomega.Equal(wrappedErr))
|
|
})
|
|
ginkgo.It("returns nil when no wrapped error exists", func() {
|
|
failureNoWrap := failures.Wrap(testMessage, testID, nil)
|
|
gomega.Expect(failureNoWrap.Unwrap()).To(gomega.Succeed())
|
|
})
|
|
})
|
|
|
|
ginkgo.Describe("Is method", func() {
|
|
ginkgo.It("returns true for failures with the same ID", func() {
|
|
f1 := failures.Wrap("first", testID, nil)
|
|
f2 := failures.Wrap("second", testID, nil)
|
|
gomega.Expect(f1.Is(f2)).To(gomega.BeTrue())
|
|
gomega.Expect(f2.Is(f1)).To(gomega.BeTrue())
|
|
})
|
|
ginkgo.It("returns false for failures with different IDs", func() {
|
|
f1 := failures.Wrap("first", testID, nil)
|
|
f2 := failures.Wrap("second", testID+1, nil)
|
|
gomega.Expect(f1.Is(f2)).To(gomega.BeFalse())
|
|
gomega.Expect(f2.Is(f1)).To(gomega.BeFalse())
|
|
})
|
|
ginkgo.It("returns false when comparing with a non-failure error", func() {
|
|
f1 := failures.Wrap("first", testID, nil)
|
|
gomega.Expect(f1.Is(wrappedErr)).To(gomega.BeFalse())
|
|
})
|
|
})
|
|
})
|
|
|
|
ginkgo.Describe("edge cases", func() {
|
|
ginkgo.When("wrapping with an empty message", func() {
|
|
ginkgo.It("handles an empty message gracefully", func() {
|
|
failure := failures.Wrap("", testID, wrappedErr)
|
|
gomega.Expect(failure.Error()).To(gomega.Equal(": " + wrappedErr.Error()))
|
|
gomega.Expect(failure.ID()).To(gomega.Equal(testID))
|
|
gomega.Expect(failure.Unwrap()).To(gomega.Equal(wrappedErr))
|
|
})
|
|
})
|
|
|
|
ginkgo.When("wrapping with nil error and no args", func() {
|
|
ginkgo.It("returns a valid failure with just message and ID", func() {
|
|
failure := failures.Wrap(testMessage, testID, nil)
|
|
gomega.Expect(failure.Error()).To(gomega.Equal(testMessage))
|
|
gomega.Expect(failure.ID()).To(gomega.Equal(testID))
|
|
gomega.Expect(failure.Unwrap()).To(gomega.Succeed())
|
|
})
|
|
})
|
|
|
|
ginkgo.When("using multiple wrapped failures", func() {
|
|
ginkgo.It("correctly chains and unwraps multiple errors", func() {
|
|
innerErr := errors.New("inner error")
|
|
middleErr := failures.Wrap("middle", testID+1, innerErr)
|
|
outerErr := failures.Wrap("outer", testID, middleErr)
|
|
gomega.Expect(outerErr.Error()).To(gomega.Equal("outer: middle: inner error"))
|
|
gomega.Expect(outerErr.ID()).To(gomega.Equal(testID))
|
|
gomega.Expect(outerErr.Unwrap()).To(gomega.Equal(middleErr))
|
|
gomega.Expect(middleErr.Unwrap()).To(gomega.Equal(innerErr))
|
|
})
|
|
})
|
|
})
|
|
|
|
ginkgo.Describe("integration-like scenarios", func() {
|
|
ginkgo.It("works with standard error wrapping utilities", func() {
|
|
innerErr := errors.New("inner error")
|
|
failure := failures.Wrap("wrapped failure", testID, innerErr)
|
|
gomega.Expect(errors.Is(failure, innerErr)).To(gomega.BeTrue()) // Matches wrapped error
|
|
gomega.Expect(errors.Unwrap(failure)).To(gomega.Equal(innerErr))
|
|
})
|
|
|
|
ginkgo.It("handles fmt.Errorf wrapping", func() {
|
|
failure := failures.Wrap("failure", testID, nil)
|
|
wrapped := fmt.Errorf("additional context: %w", failure)
|
|
gomega.Expect(wrapped.Error()).To(gomega.Equal("additional context: failure"))
|
|
gomega.Expect(errors.Unwrap(wrapped)).To(gomega.Equal(failure))
|
|
})
|
|
})
|
|
|
|
ginkgo.Describe("testutils integration", func() {
|
|
ginkgo.It("can use TestLogger for logging failures", func() {
|
|
// Demonstrate compatibility with testutils logger
|
|
failure := failures.Wrap("logged failure", testID, nil)
|
|
logger := testutils.TestLogger()
|
|
logger.Printf("Error occurred: %v", failure)
|
|
// No assertion needed; ensures no panic during logging
|
|
})
|
|
})
|
|
})
|