7
"github.com/onsi/gomega/format"
8
"github.com/onsi/gomega/types"
11
type Assertion struct {
12
actuals []interface{} // actual value plus all extra values
13
actualIndex int // value to pass to the matcher
14
vet vetinari // the vet to call before calling Gomega matcher
19
// ...obligatory discworld reference, as "vetineer" doesn't sound ... quite right.
20
type vetinari func(assertion *Assertion, optionalDescription ...interface{}) bool
22
func NewAssertion(actualInput interface{}, g *Gomega, offset int, extra ...interface{}) *Assertion {
24
actuals: append([]interface{}{actualInput}, extra...),
26
vet: (*Assertion).vetActuals,
32
func (assertion *Assertion) WithOffset(offset int) types.Assertion {
33
assertion.offset = offset
37
func (assertion *Assertion) Error() types.Assertion {
39
actuals: assertion.actuals,
40
actualIndex: len(assertion.actuals) - 1,
41
vet: (*Assertion).vetError,
42
offset: assertion.offset,
47
func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
49
vetOptionalDescription("Assertion", optionalDescription...)
50
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
53
func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
55
vetOptionalDescription("Assertion", optionalDescription...)
56
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
59
func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
61
vetOptionalDescription("Assertion", optionalDescription...)
62
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
65
func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
67
vetOptionalDescription("Assertion", optionalDescription...)
68
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
71
func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
73
vetOptionalDescription("Assertion", optionalDescription...)
74
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
77
func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) string {
78
switch len(optionalDescription) {
82
if describe, ok := optionalDescription[0].(func() string); ok {
83
return describe() + "\n"
86
return fmt.Sprintf(optionalDescription[0].(string), optionalDescription[1:]...) + "\n"
89
func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool {
90
actualInput := assertion.actuals[assertion.actualIndex]
91
matches, err := matcher.Match(actualInput)
94
description := assertion.buildDescription(optionalDescription...)
95
assertion.g.Fail(description+err.Error(), 2+assertion.offset)
98
if matches != desiredMatch {
101
message = matcher.FailureMessage(actualInput)
103
message = matcher.NegatedFailureMessage(actualInput)
105
description := assertion.buildDescription(optionalDescription...)
106
assertion.g.Fail(description+message, 2+assertion.offset)
113
// vetActuals vets the actual values, with the (optional) exception of a
114
// specific value, such as the first value in case non-error assertions, or the
115
// last value in case of Error()-based assertions.
116
func (assertion *Assertion) vetActuals(optionalDescription ...interface{}) bool {
117
success, message := vetActuals(assertion.actuals, assertion.actualIndex)
122
description := assertion.buildDescription(optionalDescription...)
123
assertion.g.THelper()
124
assertion.g.Fail(description+message, 2+assertion.offset)
128
// vetError vets the actual values, except for the final error value, in case
129
// the final error value is non-zero. Otherwise, it doesn't vet the actual
130
// values, as these are allowed to take on any values unless there is a non-zero
132
func (assertion *Assertion) vetError(optionalDescription ...interface{}) bool {
133
if err := assertion.actuals[assertion.actualIndex]; err != nil {
134
// Go error result idiom: all other actual values must be zero values.
135
return assertion.vetActuals(optionalDescription...)
140
// vetActuals vets a slice of actual values, optionally skipping a particular
141
// value slice element, such as the first or last value slice element.
142
func vetActuals(actuals []interface{}, skipIndex int) (bool, string) {
143
for i, actual := range actuals {
148
zeroValue := reflect.Zero(reflect.TypeOf(actual)).Interface()
149
if !reflect.DeepEqual(zeroValue, actual) {
151
if err, ok := actual.(error); ok {
152
message = fmt.Sprintf("Unexpected error: %s\n%s", err, format.Object(err, 1))
154
message = fmt.Sprintf("Unexpected non-nil/non-zero argument at index %d:\n\t<%T>: %#v", i, actual, actual)
156
return false, message