@@ -128,7 +128,7 @@ MethodLoop:
128
128
// if RBAC will disallow the request. The returned error should
129
129
// be expected to be a NotAuthorizedError.
130
130
erroredResp := reflect .ValueOf (az ).Method (i ).Call (append ([]reflect.Value {reflect .ValueOf (ctx )}, testCase .Inputs ... ))
131
- err := findError (t , erroredResp )
131
+ _ , err := splitResp (t , erroredResp )
132
132
// This is unfortunate, but if we are using `Filter` the error returned will be nil. So filter out
133
133
// any case where the error is nil and the response is an empty slice.
134
134
if err != nil || ! hasEmptySliceResponse (erroredResp ) {
@@ -143,8 +143,14 @@ MethodLoop:
143
143
144
144
resp := reflect .ValueOf (az ).Method (i ).Call (append ([]reflect.Value {reflect .ValueOf (ctx )}, testCase .Inputs ... ))
145
145
// TODO: Should we assert the object returned is the correct one?
146
- err := findError (t , resp )
146
+ outputs , err := splitResp (t , resp )
147
147
require .NoError (t , err , "method %q returned an error" , testName )
148
+ if testCase .ExpectedOutputs != nil {
149
+ require .Equal (t , len (testCase .ExpectedOutputs ), len (outputs ), "method %q returned unexpected number of outputs" , testName )
150
+ for i := range outputs {
151
+ require .Equal (t , testCase .ExpectedOutputs [i ].Interface (), outputs [i ].Interface (), "method %q returned unexpected output %d" , testName , i )
152
+ }
153
+ }
148
154
found = true
149
155
break MethodLoop
150
156
}
@@ -177,19 +183,21 @@ func hasEmptySliceResponse(values []reflect.Value) bool {
177
183
return false
178
184
}
179
185
180
- func findError (t * testing.T , values []reflect.Value ) error {
186
+ func splitResp (t * testing.T , values []reflect.Value ) ([]reflect.Value , error ) {
187
+ outputs := []reflect.Value {}
181
188
for _ , r := range values {
182
189
if r .Type ().Implements (reflect .TypeOf ((* error )(nil )).Elem ()) {
183
190
if r .IsNil () {
184
191
// Error is found, but it's nil!
185
- return nil
192
+ return outputs , nil
186
193
}
187
194
err , ok := r .Interface ().(error )
188
195
if ! ok {
189
196
t .Fatal ("error is not an error?!" )
190
197
}
191
- return err
198
+ return outputs , err
192
199
}
200
+ outputs = append (outputs , r )
193
201
}
194
202
t .Fatal ("no expected error value found in responses (error can be nil)" )
195
203
panic ("unreachable" ) // For compile reasons
@@ -200,6 +208,8 @@ func findError(t *testing.T, values []reflect.Value) error {
200
208
type MethodCase struct {
201
209
Inputs []reflect.Value
202
210
Assertions []AssertRBAC
211
+ // Output is optional. Can assert non-error return values.
212
+ ExpectedOutputs []reflect.Value
203
213
}
204
214
205
215
// AssertRBAC contains the object and actions to be asserted.
@@ -218,13 +228,19 @@ type AssertRBAC struct {
218
228
// Inputs: inputs(workspace, template, ...),
219
229
// Assertions: asserts(workspace, rbac.ActionRead, template, rbac.ActionRead, ...),
220
230
// }
221
- func methodCase (inputs []reflect.Value , assertions []AssertRBAC ) MethodCase {
231
+ func methodCase (ins []reflect.Value , assertions []AssertRBAC ) MethodCase {
222
232
return MethodCase {
223
- Inputs : inputs ,
224
- Assertions : assertions ,
233
+ Inputs : ins ,
234
+ Assertions : assertions ,
235
+ ExpectedOutputs : nil ,
225
236
}
226
237
}
227
238
239
+ func (m MethodCase ) Outputs (outs ... any ) MethodCase {
240
+ m .ExpectedOutputs = inputs (outs ... )
241
+ return m
242
+ }
243
+
228
244
// inputs is a convenience method for creating []reflect.Value.
229
245
//
230
246
// inputs(workspace, template, ...)
@@ -236,9 +252,9 @@ func methodCase(inputs []reflect.Value, assertions []AssertRBAC) MethodCase {
236
252
// reflect.ValueOf(template),
237
253
// ...
238
254
// }
239
- func inputs (inputs ... any ) []reflect.Value {
255
+ func inputs (ins ... any ) []reflect.Value {
240
256
out := make ([]reflect.Value , 0 )
241
- for _ , input := range inputs {
257
+ for _ , input := range ins {
242
258
input := input
243
259
out = append (out , reflect .ValueOf (input ))
244
260
}
0 commit comments