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  }