Commit 52c5d834 authored by Roger Peppe's avatar Roger Peppe

changes for review

parent 0ef172d5
......@@ -388,7 +388,7 @@ func (c *notChecker) Check(got interface{}, args []interface{}, note func(key st
// For example:
//
// c.Assert("hello world", qt.Contains, "world")
// c.Assert([]int{3,5,7,99}, qt.Any, qt.Equals, 7)
// c.Assert([]int{3,5,7,99}, qt.Contains, 7)
var Contains Checker = &containsChecker{
argNames: []string{"got", "want"},
}
......@@ -397,6 +397,7 @@ type containsChecker struct {
argNames
}
// Check implements Checker.Check by checking that got contains args[0].
func (c *containsChecker) Check(got interface{}, args []interface{}, note func(key string, value interface{})) error {
if got, ok := got.(string); ok {
want, ok := args[0].(string)
......@@ -412,13 +413,13 @@ func (c *containsChecker) Check(got interface{}, args []interface{}, note func(k
}
// Any returns a Checker that uses the given checker to check elements
// of a map, slice or array. It succeeds if any element passes the
// check.
// of a slice or array or the values from a map. It succeeds if any element
// passes the check.
//
// For example:
//
// c.Assert([]int{3,5,7,99}, qt.Any(qt.Equals), 7)
// c.Assert([][]string{{"a", "b"}, {"c", "d"}, qt.Any(qt.DeepEquals), []string{"c", "d"})
// c.Assert([][]string{{"a", "b"}, {"c", "d"}}, qt.Any(qt.DeepEquals), []string{"c", "d"})
//
// See also All and Contains.
func Any(c Checker) Checker {
......@@ -433,12 +434,19 @@ type anyChecker struct {
elemChecker Checker
}
// Check implements Checker.Check by checking that one of the elements of
// got passes the c.elemChecker check.
func (c *anyChecker) Check(got interface{}, args []interface{}, note func(key string, value interface{})) error {
iter, err := newIter(got)
if err != nil {
return BadCheckf("%v", err)
}
for iter.next() {
// For the time being, discard the notes added by the sub-checker,
// because it's not clear what a good behaviour would be.
// Should we print all the failed check for all elements? If there's only
// one element in the container, the answer is probably yes,
// but let's leave it for now.
err := c.elemChecker.Check(
iter.value().Interface(),
args,
......@@ -455,7 +463,8 @@ func (c *anyChecker) Check(got interface{}, args []interface{}, note func(key st
}
// All returns a Checker that uses the given checker to check elements
// of a map, slice or array. It succeeds if all elements pass the check.
// of slice or array or the values of a map. It succeeds if all elements
// pass the check.
// On failure it prints the error from the first index that failed.
//
// For example:
......@@ -476,6 +485,8 @@ type allChecker struct {
elemChecker Checker
}
// Check implement Checker.Check by checking that all the elements of got
// pass the c.elemChecker check.
func (c *allChecker) Check(got interface{}, args []interface{}, notef func(key string, value interface{})) error {
iter, err := newIter(got)
if err != nil {
......
......@@ -1982,6 +1982,38 @@ container:
regexp:
".*e.*"
`,
}, {
about: "All nested match",
checker: qt.All(qt.All(qt.Matches)),
got: [][]string{{"hello", "goodbye"}, {"red", "blue"}, {}},
args: []interface{}{".*e.*"},
expectedNegateFailure: `
error:
unexpected success
container:
[][]string{
{"hello", "goodbye"},
{"red", "blue"},
{},
}
regexp:
".*e.*"
`,
}, {
about: "All nested mismatch",
checker: qt.All(qt.All(qt.Matches)),
got: [][]string{{"hello", "goodbye"}, {"black", "blue"}, {}},
args: []interface{}{".*e.*"},
expectedCheckFailure: `
error:
mismatch at index 1
error:
mismatch at index 0
error:
value does not match regexp
first mismatched element:
"black"
`,
}, {
about: "All slice mismatch",
checker: qt.All(qt.Matches),
......@@ -2042,19 +2074,6 @@ error:
error:
bad check: at index 0: bad check: regexp is not a string
`,
}, {
about: "Any with non-container",
checker: qt.Any(qt.Equals),
got: 5,
args: []interface{}{5},
expectedCheckFailure: `
error:
bad check: map, slice or array required
`,
expectedNegateFailure: `
error:
bad check: map, slice or array required
`,
}, {
about: "All with non-container",
checker: qt.All(qt.Equals),
......@@ -2081,6 +2100,19 @@ error:
first mismatched element:
"black"
`,
}, {
about: "Any with non-container",
checker: qt.Any(qt.Equals),
got: 5,
args: []interface{}{5},
expectedCheckFailure: `
error:
bad check: map, slice or array required
`,
expectedNegateFailure: `
error:
bad check: map, slice or array required
`,
}, {
about: "Any no match",
checker: qt.Any(qt.Equals),
......
// Licensed under the MIT license, see LICENCE file for details.
package quicktest
import (
......@@ -5,12 +7,19 @@ import (
"reflect"
)
// containerIter provides an interface for iterating over a container
// (map, slice or array).
type containerIter interface {
// next advances to the next item in the container.
next() bool
// key returns the current key as a string.
key() string
// value returns the current value.
value() reflect.Value
}
// newIter returns an iterator over x which must be a map, slice
// or array.
func newIter(x interface{}) (containerIter, error) {
v := reflect.ValueOf(x)
switch v.Kind() {
......@@ -26,6 +35,7 @@ func newIter(x interface{}) (containerIter, error) {
}
}
// sliceIter implements containerIter for slices and arrays.
type sliceIter struct {
v reflect.Value
index int
......
// Licensed under the MIT license, see LICENCE file for details.
// +build go1.12
package quicktest
......@@ -11,6 +13,7 @@ func newMapIter(v reflect.Value) containerIter {
return mapIter{v.MapRange()}
}
// mapIter implements containerIter for maps.
type mapIter struct {
iter *reflect.MapIter
}
......
// Licensed under the MIT license, see LICENCE file for details.
// +build !go1.12
package quicktest
......@@ -15,6 +17,8 @@ func newMapIter(v reflect.Value) containerIter {
}
}
// mapIter implements containerIter for maps prior to the
// introduction of reflect.Value.MapRange in Go 1.12.
type mapIter struct {
v reflect.Value
keys []reflect.Value
......
// Licensed under the MIT license, see LICENCE file for details.
package quicktest_test
import (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment