consist_of.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // untested sections: 3
  2. package matchers
  3. import (
  4. "fmt"
  5. "reflect"
  6. "github.com/onsi/gomega/format"
  7. "github.com/onsi/gomega/matchers/support/goraph/bipartitegraph"
  8. )
  9. type ConsistOfMatcher struct {
  10. Elements []interface{}
  11. }
  12. func (matcher *ConsistOfMatcher) Match(actual interface{}) (success bool, err error) {
  13. if !isArrayOrSlice(actual) && !isMap(actual) {
  14. return false, fmt.Errorf("ConsistOf matcher expects an array/slice/map. Got:\n%s", format.Object(actual, 1))
  15. }
  16. elements := matcher.Elements
  17. if len(matcher.Elements) == 1 && isArrayOrSlice(matcher.Elements[0]) {
  18. elements = []interface{}{}
  19. value := reflect.ValueOf(matcher.Elements[0])
  20. for i := 0; i < value.Len(); i++ {
  21. elements = append(elements, value.Index(i).Interface())
  22. }
  23. }
  24. matchers := []interface{}{}
  25. for _, element := range elements {
  26. matcher, isMatcher := element.(omegaMatcher)
  27. if !isMatcher {
  28. matcher = &EqualMatcher{Expected: element}
  29. }
  30. matchers = append(matchers, matcher)
  31. }
  32. values := matcher.valuesOf(actual)
  33. if len(values) != len(matchers) {
  34. return false, nil
  35. }
  36. neighbours := func(v, m interface{}) (bool, error) {
  37. match, err := m.(omegaMatcher).Match(v)
  38. return match && err == nil, nil
  39. }
  40. bipartiteGraph, err := bipartitegraph.NewBipartiteGraph(values, matchers, neighbours)
  41. if err != nil {
  42. return false, err
  43. }
  44. return len(bipartiteGraph.LargestMatching()) == len(values), nil
  45. }
  46. func (matcher *ConsistOfMatcher) valuesOf(actual interface{}) []interface{} {
  47. value := reflect.ValueOf(actual)
  48. values := []interface{}{}
  49. if isMap(actual) {
  50. keys := value.MapKeys()
  51. for i := 0; i < value.Len(); i++ {
  52. values = append(values, value.MapIndex(keys[i]).Interface())
  53. }
  54. } else {
  55. for i := 0; i < value.Len(); i++ {
  56. values = append(values, value.Index(i).Interface())
  57. }
  58. }
  59. return values
  60. }
  61. func (matcher *ConsistOfMatcher) FailureMessage(actual interface{}) (message string) {
  62. return format.Message(actual, "to consist of", matcher.Elements)
  63. }
  64. func (matcher *ConsistOfMatcher) NegatedFailureMessage(actual interface{}) (message string) {
  65. return format.Message(actual, "not to consist of", matcher.Elements)
  66. }