1// Copyright 2019 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
5package main
6
7import (
8	"bytes"
9	"fmt"
10	"reflect"
11	"testing"
12)
13
14func TestRun(t *testing.T) {
15	out := &bytes.Buffer{}
16	in := bytes.NewBuffer([]byte(`
17test.com/A@v1.0.0 test.com/B@v1.2.3
18test.com/B@v1.0.0 test.com/C@v4.5.6
19`))
20	if err := modgraphviz(in, out); err != nil {
21		t.Fatal(err)
22	}
23
24	gotGraph := string(out.Bytes())
25	wantGraph := `digraph gomodgraph {
26	node [ shape=rectangle fontsize=12 ]
27	"test.com/A@v1.0.0" -> "test.com/B@v1.2.3"
28	"test.com/B@v1.0.0" -> "test.com/C@v4.5.6"
29	"test.com/A@v1.0.0" [style = filled, fillcolor = green]
30	"test.com/B@v1.2.3" [style = filled, fillcolor = green]
31	"test.com/C@v4.5.6" [style = filled, fillcolor = green]
32	"test.com/B@v1.0.0" [style = filled, fillcolor = gray]
33}
34`
35	if gotGraph != wantGraph {
36		t.Fatalf("\ngot: %s\nwant: %s", gotGraph, wantGraph)
37	}
38}
39
40func TestMVSPicking(t *testing.T) {
41	for _, tc := range []struct {
42		name         string
43		in           []string
44		wantPicked   []string
45		wantUnpicked []string
46	}{
47		{
48			name:         "single node",
49			in:           []string{"foo@v0.0.1"},
50			wantPicked:   []string{"foo@v0.0.1"},
51			wantUnpicked: nil,
52		},
53		{
54			name:         "duplicate same node",
55			in:           []string{"foo@v0.0.1", "foo@v0.0.1"},
56			wantPicked:   []string{"foo@v0.0.1"},
57			wantUnpicked: nil,
58		},
59		{
60			name:         "multiple semver - same major",
61			in:           []string{"foo@v1.0.0", "foo@v1.3.7", "foo@v1.2.0", "foo@v1.0.1"},
62			wantPicked:   []string{"foo@v1.3.7"},
63			wantUnpicked: []string{"foo@v1.0.0", "foo@v1.2.0", "foo@v1.0.1"},
64		},
65		{
66			name:         "multiple semver - multiple major",
67			in:           []string{"foo@v1.0.0", "foo@v1.3.7", "foo/v2@v2.2.0", "foo/v2@v2.0.1", "foo@v1.1.1"},
68			wantPicked:   []string{"foo/v2@v2.2.0", "foo@v1.3.7"},
69			wantUnpicked: []string{"foo@v1.0.0", "foo/v2@v2.0.1", "foo@v1.1.1"},
70		},
71		{
72			name:         "semver and pseudo version",
73			in:           []string{"foo@v1.0.0", "foo@v1.3.7", "foo/v2@v2.2.0", "foo/v2@v2.0.1", "foo@v1.1.1", "foo@v0.0.0-20190311183353-d8887717615a"},
74			wantPicked:   []string{"foo/v2@v2.2.0", "foo@v1.3.7"},
75			wantUnpicked: []string{"foo@v1.0.0", "foo/v2@v2.0.1", "foo@v1.1.1", "foo@v0.0.0-20190311183353-d8887717615a"},
76		},
77		{
78			name: "multiple pseudo version",
79			in: []string{
80				"foo@v0.0.0-20190311183353-d8887717615a",
81				"foo@v0.0.0-20190227222117-0694c2d4d067",
82				"foo@v0.0.0-20190312151545-0bb0c0a6e846",
83			},
84			wantPicked: []string{"foo@v0.0.0-20190312151545-0bb0c0a6e846"},
85			wantUnpicked: []string{
86				"foo@v0.0.0-20190227222117-0694c2d4d067",
87				"foo@v0.0.0-20190311183353-d8887717615a",
88			},
89		},
90		{
91			name:         "semver and suffix",
92			in:           []string{"foo@v1.0.0", "foo@v1.3.8-rc1", "foo@v1.3.7"},
93			wantPicked:   []string{"foo@v1.3.8-rc1"},
94			wantUnpicked: []string{"foo@v1.0.0", "foo@v1.3.7"},
95		},
96	} {
97		t.Run(tc.name, func(t *testing.T) {
98			buf := bytes.Buffer{}
99			for _, node := range tc.in {
100				fmt.Fprintf(&buf, "A %s\n", node)
101			}
102
103			g, err := convert(&buf)
104			if err != nil {
105				t.Fatal(err)
106			}
107
108			if !reflect.DeepEqual(g.mvsPicked, tc.wantPicked) {
109				t.Fatalf("picked: got %v, want %v", g.mvsPicked, tc.wantPicked)
110			}
111			if !reflect.DeepEqual(g.mvsUnpicked, tc.wantUnpicked) {
112				t.Fatalf("unpicked: got %v, want %v", g.mvsUnpicked, tc.wantUnpicked)
113			}
114		})
115	}
116}
117