Skip to content

Commit 56bf285

Browse files
Move graph Generation Logic to a separate helper func (#51)
- Refactor and move the graph generation logic out of getDepInfo method to a separate helper func - Add test case for the helper based on a dummy go mod output
1 parent c124aeb commit 56bf285

File tree

2 files changed

+101
-35
lines changed

2 files changed

+101
-35
lines changed

cmd/utils.go

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ type DependencyOverview struct {
4343
}
4444

4545
func getDepInfo(mainModules []string) *DependencyOverview {
46-
depGraph := DependencyOverview{MainModules: mainModules}
4746
// get output of "go mod graph" in a string
4847
goModGraph := exec.Command("go", "mod", "graph")
4948
goModGraphOutput, err := goModGraph.Output()
@@ -53,40 +52,7 @@ func getDepInfo(mainModules []string) *DependencyOverview {
5352
goModGraphOutputString := string(goModGraphOutput)
5453

5554
// create a graph of dependencies from that output
56-
graph := make(map[string][]string)
57-
scanner := bufio.NewScanner(strings.NewReader(goModGraphOutputString))
58-
59-
for scanner.Scan() {
60-
line := scanner.Text()
61-
words := strings.Fields(line)
62-
// remove versions
63-
words[0] = (strings.Split(words[0], "@"))[0]
64-
words[1] = (strings.Split(words[1], "@"))[0]
65-
66-
// we don't want to add the same dep again
67-
if !contains(graph[words[0]], words[1]) {
68-
graph[words[0]] = append(graph[words[0]], words[1])
69-
}
70-
71-
if len(depGraph.MainModules) == 0 {
72-
depGraph.MainModules = append(depGraph.MainModules, words[0])
73-
}
74-
75-
// if the LHS is a mainModule
76-
// then RHS is a direct dep else transitive dep
77-
if contains(depGraph.MainModules, words[0]) && contains(depGraph.MainModules, words[1]) {
78-
continue
79-
} else if contains(depGraph.MainModules, words[0]) {
80-
if !contains(depGraph.DirectDepList, words[1]) {
81-
depGraph.DirectDepList = append(depGraph.DirectDepList, words[1])
82-
}
83-
} else if !contains(depGraph.MainModules, words[0]) {
84-
if !contains(depGraph.TransDepList, words[1]) {
85-
depGraph.TransDepList = append(depGraph.TransDepList, words[1])
86-
}
87-
}
88-
}
89-
depGraph.Graph = graph
55+
depGraph := generateGraph(goModGraphOutputString, mainModules)
9056
return &depGraph
9157
}
9258

@@ -145,3 +111,44 @@ func sliceContains(val []Chain, key Chain) bool {
145111
}
146112
return false
147113
}
114+
115+
func generateGraph(goModGraphOutputString string, mainModules []string) DependencyOverview {
116+
depGraph := DependencyOverview{MainModules: mainModules}
117+
graph := make(map[string][]string)
118+
scanner := bufio.NewScanner(strings.NewReader(goModGraphOutputString))
119+
120+
for scanner.Scan() {
121+
line := scanner.Text()
122+
words := strings.Fields(line)
123+
// remove versions
124+
words[0] = (strings.Split(words[0], "@"))[0]
125+
words[1] = (strings.Split(words[1], "@"))[0]
126+
127+
// we don't want to add the same dep again
128+
if !contains(graph[words[0]], words[1]) {
129+
graph[words[0]] = append(graph[words[0]], words[1])
130+
}
131+
132+
if len(depGraph.MainModules) == 0 {
133+
depGraph.MainModules = append(depGraph.MainModules, words[0])
134+
}
135+
136+
// if the LHS is a mainModule
137+
// then RHS is a direct dep else transitive dep
138+
if contains(depGraph.MainModules, words[0]) && contains(depGraph.MainModules, words[1]) {
139+
continue
140+
} else if contains(depGraph.MainModules, words[0]) {
141+
if !contains(depGraph.DirectDepList, words[1]) {
142+
depGraph.DirectDepList = append(depGraph.DirectDepList, words[1])
143+
}
144+
} else if !contains(depGraph.MainModules, words[0]) {
145+
if !contains(depGraph.TransDepList, words[1]) {
146+
depGraph.TransDepList = append(depGraph.TransDepList, words[1])
147+
}
148+
}
149+
}
150+
151+
depGraph.Graph = graph
152+
153+
return depGraph
154+
}

cmd/utils_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,3 +354,62 @@ func Test_sliceContains_Fail(t *testing.T) {
354354
t.Errorf("Slice a should not have b")
355355
}
356356
}
357+
358+
func getGoModGraphTestData() string {
359+
/*
360+
Graph:
361+
A
362+
/ | \
363+
G B D
364+
| \ | / \
365+
F C E
366+
*/
367+
goModGraphOutputString := `[email protected] [email protected]
368+
369+
370+
371+
372+
373+
374+
375+
376+
return goModGraphOutputString
377+
}
378+
func Test_generateGraph_empty_mainModule(t *testing.T) {
379+
depGraph := generateGraph(getGoModGraphTestData(), nil)
380+
381+
transitiveDependencyList := []string{"F", "C", "E"}
382+
directDependencyList := []string{"G", "B", "D"}
383+
384+
if depGraph.MainModules[0] != "A" {
385+
t.Errorf(`"A" must be the main module`)
386+
}
387+
388+
if !isSliceSame(depGraph.DirectDepList, directDependencyList) {
389+
t.Errorf("Expected direct dependecies are %s but got %s", directDependencyList, depGraph.DirectDepList)
390+
}
391+
392+
if !isSliceSame(depGraph.TransDepList, transitiveDependencyList) {
393+
t.Errorf("Expected transitive dependencies are %s but got %s", transitiveDependencyList, depGraph.TransDepList)
394+
}
395+
}
396+
397+
func Test_generateGraph_custom_mainModule(t *testing.T) {
398+
mainModules := []string{"A", "D"}
399+
depGraph := generateGraph(getGoModGraphTestData(), mainModules)
400+
401+
transitiveDependencyList := []string{"F", "C"}
402+
directDependencyList := []string{"G", "B", "C", "E"}
403+
404+
if !isSliceSame(depGraph.MainModules, mainModules) {
405+
t.Errorf("Expected mainModules are %s but got %s", mainModules, depGraph.MainModules)
406+
}
407+
408+
if !isSliceSame(depGraph.DirectDepList, directDependencyList) {
409+
t.Errorf("Expected direct dependecies are %s but got %s", directDependencyList, depGraph.DirectDepList)
410+
}
411+
412+
if !isSliceSame(depGraph.TransDepList, transitiveDependencyList) {
413+
t.Errorf("Expected transitive dependencies are %s but got %s", transitiveDependencyList, depGraph.TransDepList)
414+
}
415+
}

0 commit comments

Comments
 (0)