@@ -26,50 +26,16 @@ import (
26
26
field "k8s.io/apimachinery/pkg/util/validation/field"
27
27
)
28
28
29
- // MatchErrors compares two ErrorLists with the specified matcher, and fails
30
- // the test if they don't match. If a given "want" error matches multiple "got"
31
- // errors, they will all be consumed. This might be OK (e.g. if there are
32
- // multiple errors on the same field from the same origin) or it might be an
33
- // insufficiently specific matcher, so these will be logged.
34
- func MatchErrors (t * testing.T , want , got field.ErrorList , matcher * Matcher ) {
35
- t .Helper ()
36
-
37
- remaining := got
38
- for _ , w := range want {
39
- tmp := make (field.ErrorList , 0 , len (remaining ))
40
- n := 0
41
- for _ , g := range remaining {
42
- if matcher .Matches (w , g ) {
43
- n ++
44
- } else {
45
- tmp = append (tmp , g )
46
- }
47
- }
48
- if n == 0 {
49
- t .Errorf ("expected an error matching:\n %s" , matcher .Render (w ))
50
- } else if n > 1 {
51
- // This is not necessarily and error, but it's worth logging in
52
- // case it's not what the test author intended.
53
- t .Logf ("multiple errors matched:\n %s" , matcher .Render (w ))
54
- }
55
- remaining = tmp
56
- }
57
- if len (remaining ) > 0 {
58
- for _ , e := range remaining {
59
- t .Errorf ("unmatched error:\n %s" , Match ().Exactly ().Render (e ))
60
- }
61
- }
62
- }
63
-
64
- // Match returns a new Matcher.
65
- func Match () * Matcher {
66
- return & Matcher {}
67
- }
68
-
69
- // Matcher is a helper for comparing field.Error objects.
70
- type Matcher struct {
71
- matchType bool
72
- matchField bool
29
+ // ErrorMatcher is a helper for comparing field.Error objects.
30
+ type ErrorMatcher struct {
31
+ // TODO(thockin): consider whether type is ever NOT required, maybe just
32
+ // assume it.
33
+ matchType bool
34
+ // TODO(thockin): consider whether field could be assumed - if the
35
+ // "want" error has a nil field, don't match on field.
36
+ matchField bool
37
+ // TODO(thockin): consider whether value could be assumed - if the
38
+ // "want" error has a nil value, don't match on field.
73
39
matchValue bool
74
40
matchOrigin bool
75
41
matchDetail func (want , got string ) bool
@@ -78,7 +44,7 @@ type Matcher struct {
78
44
79
45
// Matches returns true if the two field.Error objects match according to the
80
46
// configured criteria.
81
- func (m * Matcher ) Matches (want , got * field.Error ) bool {
47
+ func (m ErrorMatcher ) Matches (want , got * field.Error ) bool {
82
48
if m .matchType && want .Type != got .Type {
83
49
return false
84
50
}
@@ -105,8 +71,8 @@ func (m *Matcher) Matches(want, got *field.Error) bool {
105
71
}
106
72
107
73
// Render returns a string representation of the specified Error object,
108
- // according to the criteria configured in the Matcher .
109
- func (m * Matcher ) Render (e * field.Error ) string {
74
+ // according to the criteria configured in the ErrorMatcher .
75
+ func (m ErrorMatcher ) Render (e * field.Error ) string {
110
76
buf := strings.Builder {}
111
77
112
78
comma := func () {
@@ -138,66 +104,104 @@ func (m *Matcher) Render(e *field.Error) string {
138
104
return "{" + buf .String () + "}"
139
105
}
140
106
141
- // Exactly configures the matcher to match all fields exactly.
142
- func (m * Matcher ) Exactly () * Matcher {
107
+ // Exactly returns a derived ErrorMatcher which matches all fields exactly.
108
+ func (m ErrorMatcher ) Exactly () ErrorMatcher {
143
109
return m .ByType ().ByField ().ByValue ().ByOrigin ().ByDetailExact ()
144
110
}
145
111
146
- // Exactly configures the matcher to match errors by type.
147
- func (m * Matcher ) ByType () * Matcher {
112
+ // ByType returns a derived ErrorMatcher which also matches by type.
113
+ func (m ErrorMatcher ) ByType () ErrorMatcher {
148
114
m .matchType = true
149
115
return m
150
116
}
151
117
152
- // ByField configures the matcher to match errors by field path.
153
- func (m * Matcher ) ByField () * Matcher {
118
+ // ByField returns a derived ErrorMatcher which also matches by field path.
119
+ func (m ErrorMatcher ) ByField () ErrorMatcher {
154
120
m .matchField = true
155
121
return m
156
122
}
157
123
158
- // ByValue configures the matcher to match errors by the errant value.
159
- func (m * Matcher ) ByValue () * Matcher {
124
+ // ByValue returns a derived ErrorMatcher which also matches by the errant
125
+ // value.
126
+ func (m ErrorMatcher ) ByValue () ErrorMatcher {
160
127
m .matchValue = true
161
128
return m
162
129
}
163
130
164
- // ByOrigin configures the matcher to match errors by the origin.
165
- func (m * Matcher ) ByOrigin () * Matcher {
131
+ // ByOrigin returns a derived ErrorMatcher which also matches by the origin.
132
+ func (m ErrorMatcher ) ByOrigin () ErrorMatcher {
166
133
m .matchOrigin = true
167
134
return m
168
135
}
169
136
170
- // RequireOriginWhenInvalid configures the matcher to require the Origin field
171
- // to be set when the Type is Invalid and the matcher is matching by Origin.
172
- func (m * Matcher ) RequireOriginWhenInvalid () * Matcher {
137
+ // RequireOriginWhenInvalid returns a derived ErrorMatcher which also requires
138
+ // the Origin field to be set when the Type is Invalid and the matcher is
139
+ // matching by Origin.
140
+ func (m ErrorMatcher ) RequireOriginWhenInvalid () ErrorMatcher {
173
141
m .requireOriginWhenInvalid = true
174
142
return m
175
143
}
176
144
177
- // ByDetailExact configures the matcher to match errors by the exact detail
178
- // string.
179
- func (m * Matcher ) ByDetailExact () * Matcher {
145
+ // ByDetailExact returns a derived ErrorMatcher which also matches errors by
146
+ // the exact detail string.
147
+ func (m ErrorMatcher ) ByDetailExact () ErrorMatcher {
180
148
m .matchDetail = func (want , got string ) bool {
181
149
return got == want
182
150
}
183
151
return m
184
152
}
185
153
186
- // ByDetailSubstring configures the matcher to match errors by a substring of
187
- // the detail string.
188
- func (m * Matcher ) ByDetailSubstring () * Matcher {
154
+ // ByDetailSubstring returns a derived ErrorMatcher which also matches errors
155
+ // by a substring of the detail string.
156
+ func (m ErrorMatcher ) ByDetailSubstring () ErrorMatcher {
189
157
m .matchDetail = func (want , got string ) bool {
190
158
return strings .Contains (got , want )
191
159
}
192
160
return m
193
161
}
194
162
195
- // ByDetailRegexp configures the matcher to match errors by a regular
196
- // expression of the detail string, where the "want" string is assumed to be a
197
- // valid regular expression.
198
- func (m * Matcher ) ByDetailRegexp () * Matcher {
163
+ // ByDetailRegexp returns a derived ErrorMatcher which also matches errors by a
164
+ // regular expression of the detail string, where the "want" string is assumed
165
+ // to be a valid regular expression.
166
+ func (m ErrorMatcher ) ByDetailRegexp () ErrorMatcher {
199
167
m .matchDetail = func (want , got string ) bool {
200
168
return regexp .MustCompile (want ).MatchString (got )
201
169
}
202
170
return m
203
171
}
172
+
173
+ // Test compares two ErrorLists by the criteria configured in this matcher, and
174
+ // fails the test if they don't match. If a given "want" error matches multiple
175
+ // "got" errors, they will all be consumed. This might be OK (e.g. if there are
176
+ // multiple errors on the same field from the same origin) or it might be an
177
+ // insufficiently specific matcher, so these will be logged.
178
+ func (m ErrorMatcher ) Test (tb testing.TB , want , got field.ErrorList ) {
179
+ tb .Helper ()
180
+
181
+ remaining := got
182
+ for _ , w := range want {
183
+ tmp := make (field.ErrorList , 0 , len (remaining ))
184
+ n := 0
185
+ for _ , g := range remaining {
186
+ if m .Matches (w , g ) {
187
+ n ++
188
+ } else {
189
+ tmp = append (tmp , g )
190
+ }
191
+ }
192
+ if n == 0 {
193
+ tb .Errorf ("expected an error matching:\n %s" , m .Render (w ))
194
+ } else if n > 1 {
195
+ // This is not necessarily and error, but it's worth logging in
196
+ // case it's not what the test author intended.
197
+ tb .Logf ("multiple errors matched:\n %s" , m .Render (w ))
198
+ }
199
+ remaining = tmp
200
+ }
201
+ if len (remaining ) > 0 {
202
+ for _ , e := range remaining {
203
+ exactly := m .Exactly () // makes a copy
204
+ tb .Errorf ("unmatched error:\n %s" , exactly .Render (e ))
205
+ }
206
+ }
207
+ }
0 commit comments