diff --git a/mtest/massert/massert.go b/mtest/massert/massert.go index 50b3f3a..12fde86 100644 --- a/mtest/massert/massert.go +++ b/mtest/massert/massert.go @@ -290,6 +290,10 @@ func toStr(i interface{}) string { // Equal asserts that the two values are exactly equal, and uses the // reflect.DeepEqual function to determine if they are. +// +// TODO this does not currently handle the case of creating the Assertion using +// a reference type (like a map), changing one of the map's keys, and then +// calling Assert. func Equal(a, b interface{}) Assertion { return newAssertion(func() error { if !reflect.DeepEqual(a, b) { @@ -320,6 +324,10 @@ func Nil(i interface{}) Assertion { }, toStr(i)+" is nil", 0) } +type setKV struct { + k, v interface{} +} + func toSet(i interface{}, keyedMap bool) ([]interface{}, error) { v := reflect.ValueOf(i) switch v.Kind() { @@ -334,7 +342,7 @@ func toSet(i interface{}, keyedMap bool) ([]interface{}, error) { vv := make([]interface{}, len(keys)) for i := range keys { if keyedMap { - vv[i] = struct{ k, v interface{} }{ + vv[i] = setKV{ k: keys[i].Interface(), v: v.MapIndex(keys[i]).Interface(), } @@ -351,20 +359,19 @@ func toSet(i interface{}, keyedMap bool) ([]interface{}, error) { // Subset asserts that the given subset is a subset of the given set. Both must // be of the same type and may be arrays, slices, or maps. func Subset(set, subset interface{}) Assertion { + if reflect.TypeOf(set) != reflect.TypeOf(subset) { + panic(errors.New("set and subset aren't of same type")) + } + + setVV, err := toSet(set, true) + if err != nil { + panic(err) + } + subsetVV, err := toSet(subset, true) + if err != nil { + panic(err) + } return newAssertion(func() error { - if reflect.TypeOf(set) != reflect.TypeOf(subset) { - return errors.New("set and subset aren't of same type") - } - - setVV, err := toSet(set, true) - if err != nil { - return err - } - subsetVV, err := toSet(subset, true) - if err != nil { - return err - } - // this is obviously not the most efficient way to do this outer: for i := range subsetVV { @@ -383,12 +390,12 @@ func Subset(set, subset interface{}) Assertion { // 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. func Has(set, elem interface{}) Assertion { - return newAssertion(func() error { - setVV, err := toSet(set, false) - if err != nil { - return err - } + setVV, err := toSet(set, false) + if err != nil { + panic(err) + } + return newAssertion(func() error { for i := range setVV { if reflect.DeepEqual(setVV[i], elem) { return nil @@ -401,14 +408,16 @@ func Has(set, elem interface{}) Assertion { // HasKey asserts that the given set (which must be a map type) has the given // element as a key in it. func HasKey(set, elem interface{}) Assertion { + if v := reflect.ValueOf(set); v.Kind() != reflect.Map { + panic(fmt.Errorf("type %s is not a map", v.Type())) + } + setVV, err := toSet(set, true) + if err != nil { + panic(err) + } return newAssertion(func() error { - v := reflect.ValueOf(set) - if v.Kind() != reflect.Map { - return fmt.Errorf("type %s is not a map", v.Type()) - } - - for _, key := range v.MapKeys() { - if reflect.DeepEqual(key.Interface(), elem) { + for _, kv := range setVV { + if reflect.DeepEqual(kv.(setKV).k, elem) { return nil } } @@ -420,11 +429,13 @@ func HasKey(set, elem interface{}) Assertion { // set may be an array, a slice, or a map. A nil value'd set is considered to be // a length of zero. func Len(set interface{}, length int) Assertion { + setVV, err := toSet(set, false) + if err != nil { + panic(err) + } + return newAssertion(func() error { - setVV, err := toSet(set, false) - if err != nil { - return err - } else if len(setVV) != length { + if len(setVV) != length { return fmt.Errorf("set not correct length, is %d", len(setVV)) } return nil diff --git a/mtest/massert/massert_test.go b/mtest/massert/massert_test.go index 126fccd..a0357d3 100644 --- a/mtest/massert/massert_test.go +++ b/mtest/massert/massert_test.go @@ -145,15 +145,19 @@ func TestSubset(t *T) { )) Fatal(t, None( - Subset([]int64{1, 2, 3}, []int{1}), Subset([]int{}, []int{1, 2, 3}), Subset([]int{1, 2, 3}, []int{4}), Subset([]int{1, 2, 3}, []int{1, 3, 2, 4}), - Subset(map[int]int{1: 1, 2: 2}, map[int]int64{1: 1}), Subset(map[int]int{1: 1, 2: 2}, map[int]int{1: 2}), Subset(map[int]int{1: 1, 2: 2}, map[int]int{1: 1, 3: 3}), )) + + // make sure changes don't retroactively fail the assertion + m := map[int]int{1: 1, 2: 2} + a := Subset(m, map[int]int{1: 1}) + m[1] = 2 + Fatal(t, a) } func TestHas(t *T) { @@ -176,6 +180,12 @@ func TestHas(t *T) { Has(map[int]int{1: 2}, 1), Has(map[int]int{1: 2, 2: 1}, 3), )) + + // make sure changes don't retroactively fail the assertion + m := map[int]int{1: 1} + a := Has(m, 1) + m[1] = 2 + Fatal(t, a) } func TestHasKey(t *T) { @@ -186,11 +196,16 @@ func TestHasKey(t *T) { )) Fatal(t, None( - HasKey([]int{}, 1), - HasKey([]int{1}, 1), HasKey(map[int]int{}, 1), HasKey(map[int]int{2: 2}, 1), )) + + // make sure changes don't retroactively fail the assertion + m := map[int]int{1: 1} + a := HasKey(m, 1) + delete(m, 1) + Fatal(t, a) + } func TestLen(t *T) { @@ -215,4 +230,10 @@ func TestLen(t *T) { Len(map[int]int(nil), 1), Len(map[int]int{}, 1), )) + + // make sure changes don't retroactively fail the assertion + m := map[int]int{1: 1} + a := Len(m, 1) + m[2] = 2 + Fatal(t, a) }