consist_of.go 2.1 KB

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