Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
kardolus
GitHub Repository: kardolus/chatgpt-cli
Path: blob/main/vendor/github.com/onsi/gomega/matchers/have_exact_elements.go
2880 views
1
package matchers
2
3
import (
4
"fmt"
5
"reflect"
6
7
"github.com/onsi/gomega/format"
8
"github.com/onsi/gomega/matchers/internal/miter"
9
)
10
11
type mismatchFailure struct {
12
failure string
13
index int
14
}
15
16
type HaveExactElementsMatcher struct {
17
Elements []any
18
mismatchFailures []mismatchFailure
19
missingIndex int
20
extraIndex int
21
}
22
23
func (matcher *HaveExactElementsMatcher) Match(actual any) (success bool, err error) {
24
matcher.resetState()
25
26
if isMap(actual) || miter.IsSeq2(actual) {
27
return false, fmt.Errorf("HaveExactElements matcher doesn't work on map or iter.Seq2. Got:\n%s", format.Object(actual, 1))
28
}
29
30
matchers := matchers(matcher.Elements)
31
lenMatchers := len(matchers)
32
33
success = true
34
35
if miter.IsIter(actual) {
36
// In the worst case, we need to see everything before we can give our
37
// verdict. The only exception is fast fail.
38
i := 0
39
miter.IterateV(actual, func(v reflect.Value) bool {
40
if i >= lenMatchers {
41
// the iterator produces more values than we got matchers: this
42
// is not good.
43
matcher.extraIndex = i
44
success = false
45
return false
46
}
47
48
elemMatcher := matchers[i].(omegaMatcher)
49
match, err := elemMatcher.Match(v.Interface())
50
if err != nil {
51
matcher.mismatchFailures = append(matcher.mismatchFailures, mismatchFailure{
52
index: i,
53
failure: err.Error(),
54
})
55
success = false
56
} else if !match {
57
matcher.mismatchFailures = append(matcher.mismatchFailures, mismatchFailure{
58
index: i,
59
failure: elemMatcher.FailureMessage(v.Interface()),
60
})
61
success = false
62
}
63
i++
64
return true
65
})
66
if i < len(matchers) {
67
// the iterator produced less values than we got matchers: this is
68
// no good, no no no.
69
matcher.missingIndex = i
70
success = false
71
}
72
return success, nil
73
}
74
75
values := valuesOf(actual)
76
lenValues := len(values)
77
78
for i := 0; i < lenMatchers || i < lenValues; i++ {
79
if i >= lenMatchers {
80
matcher.extraIndex = i
81
success = false
82
continue
83
}
84
85
if i >= lenValues {
86
matcher.missingIndex = i
87
success = false
88
return
89
}
90
91
elemMatcher := matchers[i].(omegaMatcher)
92
match, err := elemMatcher.Match(values[i])
93
if err != nil {
94
matcher.mismatchFailures = append(matcher.mismatchFailures, mismatchFailure{
95
index: i,
96
failure: err.Error(),
97
})
98
success = false
99
} else if !match {
100
matcher.mismatchFailures = append(matcher.mismatchFailures, mismatchFailure{
101
index: i,
102
failure: elemMatcher.FailureMessage(values[i]),
103
})
104
success = false
105
}
106
}
107
108
return success, nil
109
}
110
111
func (matcher *HaveExactElementsMatcher) FailureMessage(actual any) (message string) {
112
message = format.Message(actual, "to have exact elements with", presentable(matcher.Elements))
113
if matcher.missingIndex > 0 {
114
message = fmt.Sprintf("%s\nthe missing elements start from index %d", message, matcher.missingIndex)
115
}
116
if matcher.extraIndex > 0 {
117
message = fmt.Sprintf("%s\nthe extra elements start from index %d", message, matcher.extraIndex)
118
}
119
if len(matcher.mismatchFailures) != 0 {
120
message = fmt.Sprintf("%s\nthe mismatch indexes were:", message)
121
}
122
for _, mismatch := range matcher.mismatchFailures {
123
message = fmt.Sprintf("%s\n%d: %s", message, mismatch.index, mismatch.failure)
124
}
125
return
126
}
127
128
func (matcher *HaveExactElementsMatcher) NegatedFailureMessage(actual any) (message string) {
129
return format.Message(actual, "not to contain elements", presentable(matcher.Elements))
130
}
131
132
func (matcher *HaveExactElementsMatcher) resetState() {
133
matcher.mismatchFailures = nil
134
matcher.missingIndex = 0
135
matcher.extraIndex = 0
136
}
137
138