...
1 package matchers
2
3 import (
4 "fmt"
5
6 "github.com/onsi/gomega/format"
7 )
8
9 type mismatchFailure struct {
10 failure string
11 index int
12 }
13
14 type HaveExactElementsMatcher struct {
15 Elements []interface{}
16 mismatchFailures []mismatchFailure
17 missingIndex int
18 extraIndex int
19 }
20
21 func (matcher *HaveExactElementsMatcher) Match(actual interface{}) (success bool, err error) {
22 matcher.resetState()
23
24 if isMap(actual) {
25 return false, fmt.Errorf("error")
26 }
27
28 matchers := matchers(matcher.Elements)
29 values := valuesOf(actual)
30
31 lenMatchers := len(matchers)
32 lenValues := len(values)
33
34 for i := 0; i < lenMatchers || i < lenValues; i++ {
35 if i >= lenMatchers {
36 matcher.extraIndex = i
37 continue
38 }
39
40 if i >= lenValues {
41 matcher.missingIndex = i
42 return
43 }
44
45 elemMatcher := matchers[i].(omegaMatcher)
46 match, err := elemMatcher.Match(values[i])
47 if err != nil {
48 matcher.mismatchFailures = append(matcher.mismatchFailures, mismatchFailure{
49 index: i,
50 failure: err.Error(),
51 })
52 } else if !match {
53 matcher.mismatchFailures = append(matcher.mismatchFailures, mismatchFailure{
54 index: i,
55 failure: elemMatcher.FailureMessage(values[i]),
56 })
57 }
58 }
59
60 return matcher.missingIndex+matcher.extraIndex+len(matcher.mismatchFailures) == 0, nil
61 }
62
63 func (matcher *HaveExactElementsMatcher) FailureMessage(actual interface{}) (message string) {
64 message = format.Message(actual, "to have exact elements with", presentable(matcher.Elements))
65 if matcher.missingIndex > 0 {
66 message = fmt.Sprintf("%s\nthe missing elements start from index %d", message, matcher.missingIndex)
67 }
68 if matcher.extraIndex > 0 {
69 message = fmt.Sprintf("%s\nthe extra elements start from index %d", message, matcher.extraIndex)
70 }
71 if len(matcher.mismatchFailures) != 0 {
72 message = fmt.Sprintf("%s\nthe mismatch indexes were:", message)
73 }
74 for _, mismatch := range matcher.mismatchFailures {
75 message = fmt.Sprintf("%s\n%d: %s", message, mismatch.index, mismatch.failure)
76 }
77 return
78 }
79
80 func (matcher *HaveExactElementsMatcher) NegatedFailureMessage(actual interface{}) (message string) {
81 return format.Message(actual, "not to contain elements", presentable(matcher.Elements))
82 }
83
84 func (matcher *HaveExactElementsMatcher) resetState() {
85 matcher.mismatchFailures = nil
86 matcher.missingIndex = 0
87 matcher.extraIndex = 0
88 }
89
View as plain text