func (matcher *PlanMatcher) Match(actual interface{}) (bool, error) { actualPlan, ok := actual.(atc.Plan) if !ok { return false, fmt.Errorf("expected a %T, got a %T", matcher.ExpectedPlan, actual) } expectedStripped, expectedIDs := stripIDs(matcher.ExpectedPlan) actualStripped, actualIDs := stripIDs(actualPlan) planMatcher := gomega.Equal(expectedStripped) idsMatcher := gomega.ConsistOf(expectedIDs) matched, err := planMatcher.Match(actualStripped) if err != nil { return false, err } if !matched { matcher.failedMatcher = planMatcher matcher.failedValue = actualStripped return false, nil } matched, err = idsMatcher.Match(actualIDs) if err != nil { return false, err } if !matched { matcher.failedMatcher = idsMatcher matcher.failedValue = actualIDs return false, nil } return true, nil }
func matcherToGomegaMatcher(matcher interface{}) (types.GomegaMatcher, error) { switch x := matcher.(type) { case string, int, bool, float64: return gomega.Equal(x), nil case []interface{}: var matchers []types.GomegaMatcher for _, valueI := range x { if subMatcher, ok := valueI.(types.GomegaMatcher); ok { matchers = append(matchers, subMatcher) } else { matchers = append(matchers, gomega.ContainElement(valueI)) } } return gomega.And(matchers...), nil } matcher = sanitizeExpectedValue(matcher) if matcher == nil { return nil, fmt.Errorf("Missing Required Attribute") } matcherMap, ok := matcher.(map[string]interface{}) if !ok { panic(fmt.Sprintf("Unexpected matcher type: %T\n\n", matcher)) } var matchType string var value interface{} for matchType, value = range matcherMap { break } switch matchType { case "have-prefix": return gomega.HavePrefix(value.(string)), nil case "have-suffix": return gomega.HaveSuffix(value.(string)), nil case "match-regexp": return gomega.MatchRegexp(value.(string)), nil case "have-len": value = sanitizeExpectedValue(value) return gomega.HaveLen(value.(int)), nil case "contain-element": subMatcher, err := matcherToGomegaMatcher(value) if err != nil { return nil, err } return gomega.ContainElement(subMatcher), nil case "not": subMatcher, err := matcherToGomegaMatcher(value) if err != nil { return nil, err } return gomega.Not(subMatcher), nil case "consist-of": subMatchers, err := sliceToGomega(value) if err != nil { return nil, err } var interfaceSlice []interface{} for _, d := range subMatchers { interfaceSlice = append(interfaceSlice, d) } return gomega.ConsistOf(interfaceSlice...), nil case "and": subMatchers, err := sliceToGomega(value) if err != nil { return nil, err } return gomega.And(subMatchers...), nil case "or": subMatchers, err := sliceToGomega(value) if err != nil { return nil, err } return gomega.Or(subMatchers...), nil case "gt", "ge", "lt", "le": // Golang json escapes '>', '<' symbols, so we use 'gt', 'le' instead comparator := map[string]string{ "gt": ">", "ge": ">=", "lt": "<", "le": "<=", }[matchType] return gomega.BeNumerically(comparator, value), nil default: return nil, fmt.Errorf("Unknown matcher: %s", matchType) } }
want: gomega.HavePrefix("foo"), }, { in: `{"have-suffix": "foo"}`, want: gomega.HaveSuffix("foo"), }, // Regex support is based on golangs regex engine https://golang.org/pkg/regexp/syntax/ { in: `{"match-regexp": "foo"}`, want: gomega.MatchRegexp("foo"), }, // Collection { in: `{"consist-of": ["foo"]}`, want: gomega.ConsistOf(gomega.Equal("foo")), }, { in: `{"contain-element": "foo"}`, want: gomega.ContainElement(gomega.Equal("foo")), }, { in: `{"have-len": 3}`, want: gomega.HaveLen(3), }, // Negation { in: `{"not": "foo"}`, want: gomega.Not(gomega.Equal("foo")), },
), 92) subject.Resolve(All( mockFactCountry.MustBe(OneOf(dict.AddSlice("US"))), mockFactBrowser.MustBe(NoneOf(dict.AddSlice("OP"))), ), 93) }) It("should register targets", func() { g.Expect(subject.registry).To(g.HaveLen(3)) }) DescribeTable("matching", func(fact *mockFactStruct, expected []int64) { fact.D = dict // assign dict g.Expect(subject.Select(fact)).To(g.ConsistOf(expected)) }, Entry("blank", &mockFactStruct{}, []int64{}), Entry("91 & 92 have domain inclusions, 93 matches", &mockFactStruct{Country: "US"}, []int64{93}), Entry("91 & 93 match, 92 has only one matching domain rule", &mockFactStruct{Country: "US", Domains: []string{"a.com", "d.com"}}, []int64{91, 93}), Entry("92 & 93 match, 91 excludes c.com", &mockFactStruct{Country: "US", Domains: []string{"a.com", "c.com", "d.com"}}, []int64{92, 93}), Entry("91 & 93 require US, 92 excludes CA", &mockFactStruct{Country: "CA", Domains: []string{"a.com", "c.com", "d.com"}}, []int64{}), Entry("91 & 93 have explicit country inclusions, 92 matches", &mockFactStruct{Domains: []string{"a.com", "c.com", "d.com"}}, []int64{92}), Entry("92 requires more domains, 93 excludes OP, 91 matches",