1
0
Fork 0
golang-github-nicholas-fedo.../internal/failures/failure_test.go
Daniel Baumann c0c4addb85
Adding upstream version 0.8.9.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-05-22 10:16:14 +02:00

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
})
})
})