// Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package analysis import ( "strings" "testing" ) func TestValidate(t *testing.T) { var ( dependsOnSelf = &Analyzer{ Name: "dependsOnSelf", Doc: "this analyzer depends on itself", } inCycleA = &Analyzer{ Name: "inCycleA", Doc: "this analyzer depends on inCycleB", } inCycleB = &Analyzer{ Name: "inCycleB", Doc: "this analyzer depends on inCycleA and notInCycleA", } pointsToCycle = &Analyzer{ Name: "pointsToCycle", Doc: "this analyzer depends on inCycleA", } notInCycleA = &Analyzer{ Name: "notInCycleA", Doc: "this analyzer depends on notInCycleB and notInCycleC", } notInCycleB = &Analyzer{ Name: "notInCycleB", Doc: "this analyzer depends on notInCycleC", } notInCycleC = &Analyzer{ Name: "notInCycleC", Doc: "this analyzer has no dependencies", } ) dependsOnSelf.Requires = append(dependsOnSelf.Requires, dependsOnSelf) inCycleA.Requires = append(inCycleA.Requires, inCycleB) inCycleB.Requires = append(inCycleB.Requires, inCycleA, notInCycleA) pointsToCycle.Requires = append(pointsToCycle.Requires, inCycleA) notInCycleA.Requires = append(notInCycleA.Requires, notInCycleB, notInCycleC) notInCycleB.Requires = append(notInCycleB.Requires, notInCycleC) notInCycleC.Requires = []*Analyzer{} cases := []struct { analyzers []*Analyzer wantErr bool analyzersInCycle map[string]bool }{ { []*Analyzer{dependsOnSelf}, true, map[string]bool{"dependsOnSelf": true}, }, { []*Analyzer{inCycleA, inCycleB}, true, map[string]bool{"inCycleA": true, "inCycleB": true}, }, { []*Analyzer{pointsToCycle}, true, map[string]bool{"inCycleA": true, "inCycleB": true}, }, { []*Analyzer{notInCycleA}, false, map[string]bool{}, }, } for _, c := range cases { got := Validate(c.analyzers) if !c.wantErr { if got == nil { continue } t.Errorf("got unexpected error while validating analyzers %v: %v", c.analyzers, got) } if got == nil { t.Errorf("expected error while validating analyzers %v, but got nil", c.analyzers) } err, ok := got.(*CycleInRequiresGraphError) if !ok { t.Errorf("want CycleInRequiresGraphError, got %T", err) } for a := range c.analyzersInCycle { if !err.AnalyzerNames[a] { t.Errorf("analyzer %s should be in cycle", a) } } for a := range err.AnalyzerNames { if !c.analyzersInCycle[a] { t.Errorf("analyzer %s should not be in cycle", a) } } } } func TestCycleInRequiresGraphErrorMessage(t *testing.T) { err := CycleInRequiresGraphError{} errMsg := err.Error() wantSubstring := "cycle detected" if !strings.Contains(errMsg, wantSubstring) { t.Errorf("error string %s does not contain expected substring %q", errMsg, wantSubstring) } }