github.com/abayer/test-infra@v0.0.5/prow/plugins/golint/golint_test.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package golint
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  	"testing"
    24  
    25  	"github.com/sirupsen/logrus"
    26  
    27  	"k8s.io/test-infra/prow/git/localgit"
    28  	"k8s.io/test-infra/prow/github"
    29  )
    30  
    31  var initialFiles = map[string][]byte{
    32  	"bar.go": []byte(`// Package bar does an interesting thing.
    33  package bar
    34  
    35  // Foo does a thing.
    36  func Foo(wow int) int {
    37  	return 42 + wow
    38  }
    39  `),
    40  }
    41  
    42  var pullFiles = map[string][]byte{
    43  	"qux.go": []byte(`package bar
    44  
    45  func Qux() error {
    46  	return nil
    47  }
    48  `),
    49  	"zz_generated.wowza.go": []byte(`package bar
    50  
    51  func Qux() error {
    52  	return nil
    53  }
    54  `),
    55  }
    56  
    57  type ghc struct {
    58  	genfile     []byte
    59  	pr          github.PullRequest
    60  	changes     []github.PullRequestChange
    61  	oldComments []github.ReviewComment
    62  	comment     github.DraftReview
    63  }
    64  
    65  func (g *ghc) GetPullRequestChanges(org, repo string, number int) ([]github.PullRequestChange, error) {
    66  	return g.changes, nil
    67  }
    68  
    69  func (g *ghc) CreateReview(org, repo string, number int, r github.DraftReview) error {
    70  	g.comment = r
    71  	return nil
    72  }
    73  
    74  func (g *ghc) ListPullRequestComments(org, repo string, number int) ([]github.ReviewComment, error) {
    75  	return g.oldComments, nil
    76  }
    77  
    78  func (g *ghc) GetFile(org, repo, filepath, commit string) ([]byte, error) {
    79  	return g.genfile, nil
    80  }
    81  
    82  func (g *ghc) GetPullRequest(org, repo string, number int) (*github.PullRequest, error) {
    83  	return &g.pr, nil
    84  }
    85  
    86  var e = &github.GenericCommentEvent{
    87  	Action:     github.GenericCommentActionCreated,
    88  	IssueState: "open",
    89  	Body:       "/lint",
    90  	User:       github.User{Login: "cjwagner"},
    91  	Number:     42,
    92  	IsPR:       true,
    93  	Repo: github.Repo{
    94  		Owner:    github.User{Login: "foo"},
    95  		Name:     "bar",
    96  		FullName: "foo/bar",
    97  	},
    98  }
    99  
   100  func TestLint(t *testing.T) {
   101  	lg, c, err := localgit.New()
   102  	if err != nil {
   103  		t.Fatalf("Making localgit: %v", err)
   104  	}
   105  	defer func() {
   106  		if err := lg.Clean(); err != nil {
   107  			t.Errorf("Cleaning up localgit: %v", err)
   108  		}
   109  		if err := c.Clean(); err != nil {
   110  			t.Errorf("Cleaning up client: %v", err)
   111  		}
   112  	}()
   113  	if err := lg.MakeFakeRepo("foo", "bar"); err != nil {
   114  		t.Fatalf("Making fake repo: %v", err)
   115  	}
   116  	if err := lg.AddCommit("foo", "bar", initialFiles); err != nil {
   117  		t.Fatalf("Adding initial commit: %v", err)
   118  	}
   119  	if err := lg.CheckoutNewBranch("foo", "bar", "pull/42/head"); err != nil {
   120  		t.Fatalf("Checking out pull branch: %v", err)
   121  	}
   122  	if err := lg.AddCommit("foo", "bar", pullFiles); err != nil {
   123  		t.Fatalf("Adding PR commit: %v", err)
   124  	}
   125  
   126  	gh := &ghc{
   127  		genfile: []byte("file-prefix zz_generated"),
   128  		changes: []github.PullRequestChange{
   129  			{
   130  				Filename: "qux.go",
   131  				Patch:    "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   132  			},
   133  			{
   134  				Filename: "zz_generated.wowza.go",
   135  				Patch:    "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux2() error {\n+   return nil\n+}",
   136  			},
   137  		},
   138  	}
   139  	if err := handle(gh, c, logrus.NewEntry(logrus.New()), e); err != nil {
   140  		t.Fatalf("Got error from handle: %v", err)
   141  	}
   142  	if len(gh.comment.Comments) != 2 {
   143  		t.Fatalf("Expected two comments, got %d: %v.", len(gh.comment.Comments), gh.comment.Comments)
   144  	}
   145  	for _, c := range gh.comment.Comments {
   146  		pos := c.Position
   147  		gh.oldComments = append(gh.oldComments, github.ReviewComment{
   148  			Path:     c.Path,
   149  			Position: &pos,
   150  			Body:     c.Body,
   151  		})
   152  	}
   153  	if err := handle(gh, c, logrus.NewEntry(logrus.New()), e); err != nil {
   154  		t.Fatalf("Got error from handle on second try: %v", err)
   155  	}
   156  	if len(gh.comment.Comments) != 0 {
   157  		t.Fatalf("Expected no comments, got %d: %v", len(gh.comment.Comments), gh.comment.Comments)
   158  	}
   159  
   160  	// Test that we limit comments.
   161  	badFileLines := []string{"package baz", ""}
   162  	for i := 0; i < maxComments+5; i++ {
   163  		badFileLines = append(badFileLines, fmt.Sprintf("type PublicType%d int", i))
   164  	}
   165  	gh.changes = append(gh.changes, github.PullRequestChange{
   166  		Filename: "baz.go",
   167  		Patch:    fmt.Sprintf("@@ -0,0 +1,%d @@\n+%s", len(badFileLines), strings.Join(badFileLines, "\n+")),
   168  	})
   169  	if err := lg.AddCommit("foo", "bar", map[string][]byte{"baz.go": []byte(strings.Join(badFileLines, "\n"))}); err != nil {
   170  		t.Fatalf("Adding PR commit: %v", err)
   171  	}
   172  	gh.oldComments = nil
   173  	if err := handle(gh, c, logrus.NewEntry(logrus.New()), e); err != nil {
   174  		t.Fatalf("Got error from handle on third try: %v", err)
   175  	}
   176  	if len(gh.comment.Comments) != maxComments {
   177  		t.Fatalf("Expected %d comments, got %d: %v", maxComments, len(gh.comment.Comments), gh.comment.Comments)
   178  	}
   179  }
   180  
   181  func TestAddedLines(t *testing.T) {
   182  	var testcases = []struct {
   183  		patch string
   184  		lines map[int]int
   185  		err   bool
   186  	}{
   187  		{
   188  			patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   189  			lines: map[int]int{1: 1, 2: 2, 3: 3, 4: 4, 5: 5},
   190  		},
   191  		{
   192  			patch: "@@ -29,12 +29,14 @@ import (\n \t\"github.com/sirupsen/logrus\"\n \t\"github.com/ghodss/yaml\"\n \n+\t\"k8s.io/test-infra/prow/config\"\n \t\"k8s.io/test-infra/prow/jenkins\"\n \t\"k8s.io/test-infra/prow/kube\"\n \t\"k8s.io/test-infra/prow/plank\"\n )\n \n var (\n+\tconfigPath   = flag.String(\"config-path\", \"/etc/config/config\", \"Path to config.yaml.\")\n \tbuildCluster = flag.String(\"build-cluster\", \"\", \"Path to file containing a YAML-marshalled kube.Cluster object. If empty, uses the local cluster.\")\n \n \tjenkinsURL       = flag.String(\"jenkins-url\", \"\", \"Jenkins URL\")\n@@ -47,18 +49,22 @@ var objReg = regexp.MustCompile(`^[\\w-]+$`)\n \n func main() {\n \tflag.Parse()\n-\n \tlogrus.SetFormatter(&logrus.JSONFormatter{})\n \n-\tkc, err := kube.NewClientInCluster(kube.ProwNamespace)\n+\tconfigAgent := &config.Agent{}\n+\tif err := configAgent.Start(*configPath); err != nil {\n+\t\tlogrus.WithError(err).Fatal(\"Error starting config agent.\")\n+\t}\n+\n+\tkc, err := kube.NewClientInCluster(configAgent.Config().ProwJobNamespace)\n \tif err != nil {\n \t\tlogrus.WithError(err).Fatal(\"Error getting client.\")\n \t}\n \tvar pkc *kube.Client\n \tif *buildCluster == \"\" {\n-\t\tpkc = kc.Namespace(kube.TestPodNamespace)\n+\t\tpkc = kc.Namespace(configAgent.Config().PodNamespace)\n \t} else {\n-\t\tpkc, err = kube.NewClientFromFile(*buildCluster, kube.TestPodNamespace)\n+\t\tpkc, err = kube.NewClientFromFile(*buildCluster, configAgent.Config().PodNamespace)\n \t\tif err != nil {\n \t\t\tlogrus.WithError(err).Fatal(\"Error getting kube client to build cluster.\")\n \t\t}",
   193  			lines: map[int]int{4: 32, 11: 39, 23: 54, 24: 55, 25: 56, 26: 57, 27: 58, 28: 59, 35: 65, 38: 67},
   194  		},
   195  		{
   196  			patch: "@@ -1 +0,0 @@\n-such",
   197  		},
   198  		{
   199  			patch: "@@ -1,3 +0,0 @@\n-such\n-a\n-doge",
   200  		},
   201  		{
   202  			patch: "@@ -0,0 +1 @@\n+wow",
   203  			lines: map[int]int{1: 1},
   204  		},
   205  		{
   206  			patch: "@@ -1 +1 @@\n-doge\n+wow",
   207  			lines: map[int]int{2: 1},
   208  		},
   209  		{
   210  			patch: "something strange",
   211  			err:   true,
   212  		},
   213  		{
   214  			patch: "@@ -a,3 +0,0 @@\n-wow",
   215  			err:   true,
   216  		},
   217  		{
   218  			patch: "@@ -1 +1 @@",
   219  			err:   true,
   220  		},
   221  		{
   222  			patch: "",
   223  		},
   224  	}
   225  	for _, tc := range testcases {
   226  		als, err := AddedLines(tc.patch)
   227  		if err == nil == tc.err {
   228  			t.Errorf("For patch %s\nExpected error %v, got error %v", tc.patch, tc.err, err)
   229  			continue
   230  		}
   231  		if len(als) != len(tc.lines) {
   232  			t.Errorf("For patch %s\nAdded lines has wrong length. Got %v, expected %v", tc.patch, als, tc.lines)
   233  		}
   234  		for pl, l := range tc.lines {
   235  			if als[l] != pl {
   236  				t.Errorf("For patch %s\nExpected added line %d to be %d, but got %d", tc.patch, l, pl, als[l])
   237  			}
   238  		}
   239  	}
   240  }
   241  
   242  func TestModifiedGoFiles(t *testing.T) {
   243  	lg, c, err := localgit.New()
   244  	if err != nil {
   245  		t.Fatalf("Making localgit: %v", err)
   246  	}
   247  	defer func() {
   248  		if err := lg.Clean(); err != nil {
   249  			t.Errorf("Cleaning up localgit: %v", err)
   250  		}
   251  		if err := c.Clean(); err != nil {
   252  			t.Errorf("Cleaning up client: %v", err)
   253  		}
   254  	}()
   255  	if err := lg.MakeFakeRepo("foo", "bar"); err != nil {
   256  		t.Fatalf("Making fake repo: %v", err)
   257  	}
   258  	if err := lg.AddCommit("foo", "bar", initialFiles); err != nil {
   259  		t.Fatalf("Adding initial commit: %v", err)
   260  	}
   261  	if err := lg.CheckoutNewBranch("foo", "bar", "pull/42/head"); err != nil {
   262  		t.Fatalf("Checking out pull branch: %v", err)
   263  	}
   264  	if err := lg.AddCommit("foo", "bar", pullFiles); err != nil {
   265  		t.Fatalf("Adding PR commit: %v", err)
   266  	}
   267  
   268  	var testcases = []struct {
   269  		name                  string
   270  		gh                    *ghc
   271  		expectedModifiedFiles map[string]string
   272  	}{
   273  		{
   274  			name: "modified files include vendor file",
   275  			gh: &ghc{
   276  				changes: []github.PullRequestChange{
   277  					{
   278  						Filename: "qux.go",
   279  						Patch:    "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   280  					},
   281  					{
   282  						Filename: "vendor/foo/bar.go",
   283  						Patch:    "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux2() error {\n+   return nil\n+}",
   284  					},
   285  				},
   286  			},
   287  			expectedModifiedFiles: map[string]string{
   288  				"qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   289  			},
   290  		},
   291  		{
   292  			name: "modified files include non go file",
   293  			gh: &ghc{
   294  				changes: []github.PullRequestChange{
   295  					{
   296  						Filename: "qux.go",
   297  						Patch:    "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   298  					},
   299  					{
   300  						Filename: "foo.md",
   301  						Patch:    "@@ -1,3 +1,4 @@\n+TODO",
   302  					},
   303  				},
   304  			},
   305  			expectedModifiedFiles: map[string]string{
   306  				"qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   307  			},
   308  		},
   309  		{
   310  			name: "modified files include generated file",
   311  			gh: &ghc{
   312  				genfile: []byte("file-prefix zz_generated"),
   313  				changes: []github.PullRequestChange{
   314  					{
   315  						Filename: "qux.go",
   316  						Patch:    "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   317  					},
   318  					{
   319  						Filename: "zz_generated.wowza.go",
   320  						Patch:    "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux2() error {\n+   return nil\n+}",
   321  					},
   322  				},
   323  			},
   324  			expectedModifiedFiles: map[string]string{
   325  				"qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   326  			},
   327  		},
   328  		{
   329  			name: "modified files include removed file",
   330  			gh: &ghc{
   331  				changes: []github.PullRequestChange{
   332  					{
   333  						Filename: "qux.go",
   334  						Patch:    "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   335  					},
   336  					{
   337  						Filename: "bar.go",
   338  						Status:   github.PullRequestFileRemoved,
   339  						Patch:    "@@ -1,5 +0,0 @@\n-package bar\n-\n-func Qux() error {\n-   return nil\n-}",
   340  					},
   341  				},
   342  			},
   343  			expectedModifiedFiles: map[string]string{
   344  				"qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   345  			},
   346  		},
   347  		{
   348  			name: "modified files include renamed file",
   349  			gh: &ghc{
   350  				changes: []github.PullRequestChange{
   351  					{
   352  						Filename: "qux.go",
   353  						Patch:    "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   354  					},
   355  					{
   356  						Filename: "bar.go",
   357  						Status:   github.PullRequestFileRenamed,
   358  					},
   359  				},
   360  			},
   361  			expectedModifiedFiles: map[string]string{
   362  				"qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   363  			},
   364  		},
   365  		{
   366  			name: "added and modified files",
   367  			gh: &ghc{
   368  				changes: []github.PullRequestChange{
   369  					{
   370  						Filename: "qux.go",
   371  						Status:   github.PullRequestFileAdded,
   372  						Patch:    "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   373  					},
   374  					{
   375  						Filename: "bar.go",
   376  						Patch:    "@@ -0,0 +1,5 @@\n+package baz\n+\n+func Bar() error {\n+   return nil\n+}",
   377  					},
   378  				},
   379  			},
   380  			expectedModifiedFiles: map[string]string{
   381  				"qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+   return nil\n+}",
   382  				"bar.go": "@@ -0,0 +1,5 @@\n+package baz\n+\n+func Bar() error {\n+   return nil\n+}",
   383  			},
   384  		},
   385  		{
   386  			name: "removed and renamed files",
   387  			gh: &ghc{
   388  				changes: []github.PullRequestChange{
   389  					{
   390  						Filename: "qux.go",
   391  						Status:   github.PullRequestFileRemoved,
   392  						Patch:    "@@ -1,5 +0,0 @@\n-package bar\n-\n-func Qux() error {\n-   return nil\n-}",
   393  					},
   394  					{
   395  						Filename: "bar.go",
   396  						Status:   github.PullRequestFileRenamed,
   397  					},
   398  				},
   399  			},
   400  			expectedModifiedFiles: map[string]string{},
   401  		},
   402  	}
   403  	for _, tc := range testcases {
   404  		actualModifiedFiles, _ := modifiedGoFiles(tc.gh, "foo", "bar", 9527, "0ebb33b")
   405  		if !reflect.DeepEqual(tc.expectedModifiedFiles, actualModifiedFiles) {
   406  			t.Errorf("Expected: %#v, Got %#v in case %s.", tc.expectedModifiedFiles, actualModifiedFiles, tc.name)
   407  		}
   408  	}
   409  }