github.com/golang/dep@v0.5.4/cmd/dep/graphviz_test.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "reflect" 9 "testing" 10 11 "github.com/golang/dep/internal/test" 12 ) 13 14 func TestEmptyProject(t *testing.T) { 15 h := test.NewHelper(t) 16 h.Parallel() 17 defer h.Cleanup() 18 19 g := new(graphviz).New() 20 21 b := g.output("") 22 want := h.GetTestFileString("graphviz/empty.dot") 23 24 if b.String() != want { 25 t.Fatalf("expected '%v', got '%v'", want, b.String()) 26 } 27 } 28 29 func TestSimpleProject(t *testing.T) { 30 h := test.NewHelper(t) 31 h.Parallel() 32 defer h.Cleanup() 33 34 g := new(graphviz).New() 35 36 g.createNode("project", "", []string{"foo", "bar"}) 37 g.createNode("foo", "master", []string{"bar"}) 38 g.createNode("bar", "dev", []string{}) 39 40 b := g.output("") 41 want := h.GetTestFileString("graphviz/case1.dot") 42 if b.String() != want { 43 t.Fatalf("expected '%v', got '%v'", want, b.String()) 44 } 45 } 46 47 func TestNoLinks(t *testing.T) { 48 h := test.NewHelper(t) 49 h.Parallel() 50 defer h.Cleanup() 51 52 g := new(graphviz).New() 53 54 g.createNode("project", "", []string{}) 55 56 b := g.output("") 57 want := h.GetTestFileString("graphviz/case2.dot") 58 if b.String() != want { 59 t.Fatalf("expected '%v', got '%v'", want, b.String()) 60 } 61 } 62 63 func TestIsPathPrefix(t *testing.T) { 64 t.Parallel() 65 66 tcs := []struct { 67 path string 68 pre string 69 want bool 70 }{ 71 {"github.com/sdboyer/foo/bar", "github.com/sdboyer/foo", true}, 72 {"github.com/sdboyer/foobar", "github.com/sdboyer/foo", false}, 73 {"github.com/sdboyer/bar/foo", "github.com/sdboyer/foo", false}, 74 {"golang.org/sdboyer/bar/foo", "github.com/sdboyer/foo", false}, 75 {"golang.org/sdboyer/FOO", "github.com/sdboyer/foo", false}, 76 } 77 78 for _, tc := range tcs { 79 r := isPathPrefix(tc.path, tc.pre) 80 if tc.want != r { 81 t.Fatalf("expected '%v', got '%v'", tc.want, r) 82 } 83 } 84 } 85 86 func TestSimpleSubgraphs(t *testing.T) { 87 type testProject struct { 88 name string 89 packages map[string][]string 90 } 91 92 testCases := []struct { 93 name string 94 projects []testProject 95 targetProject string 96 outputfile string 97 }{ 98 { 99 name: "simple graph", 100 projects: []testProject{ 101 { 102 name: "ProjectA", 103 packages: map[string][]string{ 104 "ProjectA/pkgX": []string{"ProjectC/pkgZ", "ProjectB/pkgX"}, 105 "ProjectA/pkgY": []string{"ProjectC/pkgX"}, 106 }, 107 }, 108 { 109 name: "ProjectB", 110 packages: map[string][]string{ 111 "ProjectB/pkgX": []string{}, 112 "ProjectB/pkgY": []string{"ProjectA/pkgY", "ProjectC/pkgZ"}, 113 }, 114 }, 115 { 116 name: "ProjectC", 117 packages: map[string][]string{ 118 "ProjectC/pkgX": []string{}, 119 "ProjectC/pkgY": []string{}, 120 "ProjectC/pkgZ": []string{}, 121 }, 122 }, 123 }, 124 targetProject: "ProjectC", 125 outputfile: "graphviz/subgraph1.dot", 126 }, 127 { 128 name: "edges from and to root projects", 129 projects: []testProject{ 130 { 131 name: "ProjectB", 132 packages: map[string][]string{ 133 "ProjectB": []string{"ProjectC/pkgX", "ProjectC"}, 134 "ProjectB/pkgX": []string{}, 135 "ProjectB/pkgY": []string{"ProjectA/pkgY", "ProjectC/pkgZ"}, 136 "ProjectB/pkgZ": []string{"ProjectC"}, 137 }, 138 }, 139 { 140 name: "ProjectC", 141 packages: map[string][]string{ 142 "ProjectC/pkgX": []string{}, 143 "ProjectC/pkgY": []string{}, 144 "ProjectC/pkgZ": []string{}, 145 }, 146 }, 147 }, 148 targetProject: "ProjectC", 149 outputfile: "graphviz/subgraph2.dot", 150 }, 151 { 152 name: "multi and single package projects", 153 projects: []testProject{ 154 { 155 name: "ProjectA", 156 packages: map[string][]string{ 157 "ProjectA": []string{"ProjectC/pkgX"}, 158 }, 159 }, 160 { 161 name: "ProjectB", 162 packages: map[string][]string{ 163 "ProjectB": []string{"ProjectC/pkgX", "ProjectC"}, 164 "ProjectB/pkgX": []string{}, 165 "ProjectB/pkgY": []string{"ProjectA/pkgY", "ProjectC/pkgZ"}, 166 "ProjectB/pkgZ": []string{"ProjectC"}, 167 }, 168 }, 169 { 170 name: "ProjectC", 171 packages: map[string][]string{ 172 "ProjectC/pkgX": []string{}, 173 "ProjectC/pkgY": []string{}, 174 "ProjectC/pkgZ": []string{}, 175 }, 176 }, 177 }, 178 targetProject: "ProjectC", 179 outputfile: "graphviz/subgraph3.dot", 180 }, 181 { 182 name: "relation from a cluster to a node", 183 projects: []testProject{ 184 { 185 name: "ProjectB", 186 packages: map[string][]string{ 187 "ProjectB": []string{"ProjectC/pkgX", "ProjectA"}, 188 "ProjectB/pkgX": []string{}, 189 "ProjectB/pkgY": []string{"ProjectA", "ProjectC/pkgZ"}, 190 "ProjectB/pkgZ": []string{"ProjectC"}, 191 }, 192 }, 193 { 194 name: "ProjectA", 195 packages: map[string][]string{ 196 "ProjectA": []string{"ProjectC/pkgX"}, 197 }, 198 }, 199 }, 200 targetProject: "ProjectA", 201 outputfile: "graphviz/subgraph4.dot", 202 }, 203 } 204 205 h := test.NewHelper(t) 206 h.Parallel() 207 defer h.Cleanup() 208 209 for _, tc := range testCases { 210 g := new(graphviz).New() 211 212 for _, project := range tc.projects { 213 g.createSubgraph(project.name, project.packages) 214 } 215 216 output := g.output(tc.targetProject) 217 want := h.GetTestFileString(tc.outputfile) 218 if output.String() != want { 219 t.Fatalf("expected '%v', got '%v'", want, output.String()) 220 } 221 } 222 } 223 224 func TestCreateSubgraph(t *testing.T) { 225 testCases := []struct { 226 name string 227 project string 228 pkgs map[string][]string 229 wantNodes []*gvnode 230 wantClusters map[string]*gvsubgraph 231 }{ 232 { 233 name: "Project with subpackages", 234 project: "ProjectA", 235 pkgs: map[string][]string{ 236 "ProjectA/pkgX": []string{"ProjectC/pkgZ", "ProjectB/pkgX"}, 237 "ProjectA/pkgY": []string{"ProjectC/pkgX"}, 238 }, 239 wantNodes: []*gvnode{ 240 &gvnode{ 241 project: "ProjectA/pkgX", 242 children: []string{"ProjectC/pkgZ", "ProjectB/pkgX"}, 243 }, 244 &gvnode{ 245 project: "ProjectA/pkgY", 246 children: []string{"ProjectC/pkgX"}, 247 }, 248 }, 249 wantClusters: map[string]*gvsubgraph{ 250 "ProjectA": &gvsubgraph{ 251 project: "ProjectA", 252 packages: []string{"ProjectA/pkgX", "ProjectA/pkgY"}, 253 index: 0, 254 children: []string{}, 255 }, 256 }, 257 }, 258 { 259 name: "Project with single subpackage at root", 260 project: "ProjectA", 261 pkgs: map[string][]string{ 262 "ProjectA": []string{"ProjectC/pkgZ", "ProjectB/pkgX"}, 263 }, 264 wantNodes: []*gvnode{ 265 &gvnode{ 266 project: "ProjectA", 267 children: []string{"ProjectC/pkgZ", "ProjectB/pkgX"}, 268 }, 269 }, 270 wantClusters: map[string]*gvsubgraph{}, 271 }, 272 { 273 name: "Project with subpackages and no children", 274 project: "ProjectX", 275 pkgs: map[string][]string{ 276 "ProjectX/pkgA": []string{}, 277 }, 278 wantNodes: []*gvnode{ 279 &gvnode{ 280 project: "ProjectX/pkgA", 281 children: []string{}, 282 }, 283 }, 284 wantClusters: map[string]*gvsubgraph{ 285 "ProjectX": &gvsubgraph{ 286 project: "ProjectX", 287 packages: []string{"ProjectX/pkgA"}, 288 index: 0, 289 children: []string{}, 290 }, 291 }, 292 }, 293 { 294 name: "Project with subpackage and root package with children", 295 project: "ProjectA", 296 pkgs: map[string][]string{ 297 "ProjectA": []string{"ProjectC/pkgZ", "ProjectB/pkgX"}, 298 "ProjectA/pkgX": []string{"ProjectC/pkgA"}, 299 }, 300 wantNodes: []*gvnode{ 301 &gvnode{ 302 project: "ProjectA/pkgX", 303 children: []string{"ProjectC/pkgA"}, 304 }, 305 }, 306 wantClusters: map[string]*gvsubgraph{ 307 "ProjectA": &gvsubgraph{ 308 project: "ProjectA", 309 packages: []string{"ProjectA/pkgX"}, 310 index: 0, 311 children: []string{"ProjectC/pkgZ", "ProjectB/pkgX"}, 312 }, 313 }, 314 }, 315 } 316 317 for _, tc := range testCases { 318 t.Run(tc.name, func(t *testing.T) { 319 g := new(graphviz).New() 320 321 g.createSubgraph(tc.project, tc.pkgs) 322 323 // Check the number of created nodes. 324 if len(g.ps) != len(tc.wantNodes) { 325 t.Errorf("unexpected number of nodes: \n\t(GOT) %v\n\t(WNT) %v", len(g.ps), len(tc.wantNodes)) 326 } 327 328 // Check if the expected nodes are created. 329 for i, v := range tc.wantNodes { 330 if v.project != g.ps[i].project { 331 t.Errorf("found unexpected node: \n\t(GOT) %v\n\t(WNT) %v", g.ps[i].project, v.project) 332 } 333 } 334 335 // Check the number of created clusters. 336 if len(g.clusters) != len(tc.wantClusters) { 337 t.Errorf("unexpected number of clusters: \n\t(GOT) %v\n\t(WNT) %v", len(g.clusters), len(tc.wantClusters)) 338 } 339 340 // Check if the expected clusters are created. 341 if !reflect.DeepEqual(g.clusters, tc.wantClusters) { 342 t.Errorf("unexpected clusters: \n\t(GOT) %v\n\t(WNT) %v", g.clusters, tc.wantClusters) 343 } 344 }) 345 } 346 }