github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/testhelpers/match_plan_matcher.go (about) 1 package testhelpers 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "github.com/pf-qiu/concourse/v6/atc" 9 "github.com/onsi/gomega" 10 "github.com/onsi/gomega/types" 11 ) 12 13 type PlanMatcher struct { 14 ExpectedPlan atc.Plan 15 16 failedMatcher types.GomegaMatcher 17 failedValue interface{} 18 } 19 20 func MatchPlan(plan atc.Plan) *PlanMatcher { 21 return &PlanMatcher{ 22 ExpectedPlan: plan, 23 } 24 } 25 26 func VerifyPlan(expectedPlan atc.Plan) http.HandlerFunc { 27 return func(w http.ResponseWriter, r *http.Request) { 28 var plan atc.Plan 29 err := json.NewDecoder(r.Body).Decode(&plan) 30 gomega.Expect(err).ToNot(gomega.HaveOccurred()) 31 32 gomega.Expect(plan).To(MatchPlan(expectedPlan)) 33 } 34 } 35 36 func (matcher *PlanMatcher) Match(actual interface{}) (bool, error) { 37 actualPlan, ok := actual.(atc.Plan) 38 if !ok { 39 return false, fmt.Errorf("expected a %T, got a %T", matcher.ExpectedPlan, actual) 40 } 41 42 expectedStripped, _ := stripIDs(matcher.ExpectedPlan) 43 actualStripped, actualIDs := stripIDs(actualPlan) 44 45 planMatcher := gomega.Equal(expectedStripped) 46 47 if !idsAreUnique(actualIDs) { 48 return false, fmt.Errorf("expected %#v to contain unique elements", actualIDs) 49 } 50 51 matched, err := planMatcher.Match(actualStripped) 52 if err != nil { 53 return false, err 54 } 55 56 if !matched { 57 matcher.failedMatcher = planMatcher 58 matcher.failedValue = actualStripped 59 return false, nil 60 } 61 62 return true, nil 63 } 64 65 func idsAreUnique(ids []string) bool { 66 seenIds := make(map[string]bool) 67 68 for _, id := range ids { 69 if seenIds[id] { 70 return false 71 } 72 73 seenIds[id] = true 74 } 75 76 return true 77 } 78 79 func (matcher *PlanMatcher) FailureMessage(actual interface{}) string { 80 return matcher.failedMatcher.FailureMessage(matcher.failedValue) 81 } 82 83 func (matcher *PlanMatcher) NegatedFailureMessage(actual interface{}) string { 84 return matcher.failedMatcher.NegatedFailureMessage(matcher.failedValue) 85 } 86 87 func stripIDs(plan atc.Plan) (atc.Plan, []string) { 88 ids := []string{} 89 90 // Ignore errors, since our walker doesn't return an error. 91 plan.Each(func(plan *atc.Plan) { 92 ids = append(ids, string(plan.ID)) 93 94 plan.ID = "<stripped>" 95 96 if plan.Get != nil { 97 if plan.Get.VersionFrom != nil { 98 planID := atc.PlanID("<stripped>") 99 plan.Get.VersionFrom = &planID 100 } 101 } 102 }) 103 104 return plan, ids 105 }