Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
kardolus
GitHub Repository: kardolus/chatgpt-cli
Path: blob/main/vendor/github.com/onsi/gomega/internal/assertion.go
2880 views
1
package internal
2
3
import (
4
"fmt"
5
"reflect"
6
7
"github.com/onsi/gomega/format"
8
"github.com/onsi/gomega/types"
9
)
10
11
type Assertion struct {
12
actuals []any // 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
15
offset int
16
g *Gomega
17
}
18
19
// ...obligatory discworld reference, as "vetineer" doesn't sound ... quite right.
20
type vetinari func(assertion *Assertion, optionalDescription ...any) bool
21
22
func NewAssertion(actualInput any, g *Gomega, offset int, extra ...any) *Assertion {
23
return &Assertion{
24
actuals: append([]any{actualInput}, extra...),
25
actualIndex: 0,
26
vet: (*Assertion).vetActuals,
27
offset: offset,
28
g: g,
29
}
30
}
31
32
func (assertion *Assertion) WithOffset(offset int) types.Assertion {
33
assertion.offset = offset
34
return assertion
35
}
36
37
func (assertion *Assertion) Error() types.Assertion {
38
return &Assertion{
39
actuals: assertion.actuals,
40
actualIndex: len(assertion.actuals) - 1,
41
vet: (*Assertion).vetError,
42
offset: assertion.offset,
43
g: assertion.g,
44
}
45
}
46
47
func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...any) bool {
48
assertion.g.THelper()
49
vetOptionalDescription("Assertion", optionalDescription...)
50
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
51
}
52
53
func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...any) bool {
54
assertion.g.THelper()
55
vetOptionalDescription("Assertion", optionalDescription...)
56
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
57
}
58
59
func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...any) bool {
60
assertion.g.THelper()
61
vetOptionalDescription("Assertion", optionalDescription...)
62
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
63
}
64
65
func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...any) bool {
66
assertion.g.THelper()
67
vetOptionalDescription("Assertion", optionalDescription...)
68
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
69
}
70
71
func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...any) bool {
72
assertion.g.THelper()
73
vetOptionalDescription("Assertion", optionalDescription...)
74
return assertion.vet(assertion, optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
75
}
76
77
func (assertion *Assertion) buildDescription(optionalDescription ...any) string {
78
switch len(optionalDescription) {
79
case 0:
80
return ""
81
case 1:
82
if describe, ok := optionalDescription[0].(func() string); ok {
83
return describe() + "\n"
84
}
85
}
86
return fmt.Sprintf(optionalDescription[0].(string), optionalDescription[1:]...) + "\n"
87
}
88
89
func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...any) bool {
90
actualInput := assertion.actuals[assertion.actualIndex]
91
matches, err := matcher.Match(actualInput)
92
assertion.g.THelper()
93
if err != nil {
94
description := assertion.buildDescription(optionalDescription...)
95
assertion.g.Fail(description+err.Error(), 2+assertion.offset)
96
return false
97
}
98
if matches != desiredMatch {
99
var message string
100
if desiredMatch {
101
message = matcher.FailureMessage(actualInput)
102
} else {
103
message = matcher.NegatedFailureMessage(actualInput)
104
}
105
description := assertion.buildDescription(optionalDescription...)
106
assertion.g.Fail(description+message, 2+assertion.offset)
107
return false
108
}
109
110
return true
111
}
112
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 ...any) bool {
117
success, message := vetActuals(assertion.actuals, assertion.actualIndex)
118
if success {
119
return true
120
}
121
122
description := assertion.buildDescription(optionalDescription...)
123
assertion.g.THelper()
124
assertion.g.Fail(description+message, 2+assertion.offset)
125
return false
126
}
127
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
131
// error value.
132
func (assertion *Assertion) vetError(optionalDescription ...any) 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...)
136
}
137
return true
138
}
139
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 []any, skipIndex int) (bool, string) {
143
for i, actual := range actuals {
144
if i == skipIndex {
145
continue
146
}
147
if actual != nil {
148
zeroValue := reflect.Zero(reflect.TypeOf(actual)).Interface()
149
if !reflect.DeepEqual(zeroValue, actual) {
150
var message string
151
if err, ok := actual.(error); ok {
152
message = fmt.Sprintf("Unexpected error: %s\n%s", err, format.Object(err, 1))
153
} else {
154
message = fmt.Sprintf("Unexpected non-nil/non-zero argument at index %d:\n\t<%T>: %#v", i, actual, actual)
155
}
156
return false, message
157
}
158
}
159
}
160
return true, ""
161
}
162
163