mtest/massert: ensure that values being asserted are captured at the moment the assertion is made

This commit is contained in:
Brian Picciano 2019-03-09 12:14:00 -05:00
parent 2343bda42a
commit 2496b170d8
2 changed files with 28 additions and 1 deletions

View File

@ -98,7 +98,7 @@ type assertion struct {
stack []runtime.Frame stack []runtime.Frame
} }
func newAssertion(assertFn func() error, descr string, skip int) Assertion { func newFutureAssertion(assertFn func() error, descr string, skip int) Assertion {
pcs := make([]uintptr, maxStackLen) pcs := make([]uintptr, maxStackLen)
// first skip is for runtime.Callers, second is for newAssertion, third is // first skip is for runtime.Callers, second is for newAssertion, third is
// for whatever is calling newAssertion // for whatever is calling newAssertion
@ -132,6 +132,11 @@ func newAssertion(assertFn func() error, descr string, skip int) Assertion {
return a return a
} }
func newAssertion(assertFn func() error, descr string, skip int) Assertion {
err := assertFn()
return newFutureAssertion(func() error { return err }, descr, skip+1)
}
func (a *assertion) Assert() error { func (a *assertion) Assert() error {
return a.fn() return a.fn()
} }
@ -148,6 +153,8 @@ func (a *assertion) Stack() []runtime.Frame {
// Fatal is a convenience function which performs the Assertion and calls Fatal // Fatal is a convenience function which performs the Assertion and calls Fatal
// on the testing.T instance if the assertion fails. // on the testing.T instance if the assertion fails.
//
// TODO rename to Require
func Fatal(t *testing.T, a Assertion) { func Fatal(t *testing.T, a Assertion) {
if err := a.Assert(); err != nil { if err := a.Assert(); err != nil {
t.Fatal(err) t.Fatal(err)
@ -156,6 +163,8 @@ func Fatal(t *testing.T, a Assertion) {
// Error is a convenience function which performs the Assertion and calls Error // Error is a convenience function which performs the Assertion and calls Error
// on the testing.T instance if the assertion fails. // on the testing.T instance if the assertion fails.
//
// TODO rename to Assert
func Error(t *testing.T, a Assertion) { func Error(t *testing.T, a Assertion) {
if err := a.Assert(); err != nil { if err := a.Assert(); err != nil {
t.Error(err) t.Error(err)
@ -283,11 +292,15 @@ func None(aa ...Assertion) Assertion {
} }
// Err returns an Assertion which always fails with the given error. // Err returns an Assertion which always fails with the given error.
//
// TODO rename to Error
func Err(err error) Assertion { func Err(err error) Assertion {
return newAssertion(func() error { return err }, "", 0) return newAssertion(func() error { return err }, "", 0)
} }
// Errf is like Err but allows for a formatted string. // Errf is like Err but allows for a formatted string.
//
// TODO rename to Errorf
func Errf(str string, args ...interface{}) Assertion { func Errf(str string, args ...interface{}) Assertion {
return Err(fmt.Errorf(str, args...)) return Err(fmt.Errorf(str, args...))
} }
@ -399,6 +412,8 @@ func Subset(set, subset interface{}) Assertion {
// Has asserts that the given set has the given element as a value in it. The // Has asserts that the given set has the given element as a value in it. The
// set may be an array, a slice, or a map, and if it's a map then the elem will // set may be an array, a slice, or a map, and if it's a map then the elem will
// need to be a value in it. // need to be a value in it.
//
// TODO rename to HasValue
func Has(set, elem interface{}) Assertion { func Has(set, elem interface{}) Assertion {
setVV, err := toSet(set, false) setVV, err := toSet(set, false)
if err != nil { if err != nil {
@ -438,6 +453,8 @@ func HasKey(set, elem interface{}) Assertion {
// Len asserts that the given set has the given number of elements in it. The // Len asserts that the given set has the given number of elements in it. The
// set may be an array, a slice, or a map. A nil value'd set is considered to be // set may be an array, a slice, or a map. A nil value'd set is considered to be
// a length of zero. // a length of zero.
//
// TODO rename to Length
func Len(set interface{}, length int) Assertion { func Len(set interface{}, length int) Assertion {
setVV, err := toSet(set, false) setVV, err := toSet(set, false)
if err != nil { if err != nil {

View File

@ -107,6 +107,16 @@ func TestEqual(t *T) {
Equal(1, uint64(1)), Equal(1, uint64(1)),
Equal("foo", "bar"), Equal("foo", "bar"),
)) ))
// test that assertions take in the value at the moment the assertion is
// made
var aa []Assertion
m := map[string]int{}
m["foo"] = 1
aa = append(aa, Equal(1, m["foo"]))
m["foo"] = 2
aa = append(aa, Equal(2, m["foo"]))
Fatal(t, All(aa...))
} }
func TestNil(t *T) { func TestNil(t *T) {