sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/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 "sigs.k8s.io/prow/pkg/config" 28 "sigs.k8s.io/prow/pkg/git/localgit" 29 "sigs.k8s.io/prow/pkg/github" 30 "sigs.k8s.io/prow/pkg/plugins" 31 ) 32 33 var initialFiles = map[string][]byte{ 34 "bar.go": []byte(`// Package bar does an interesting thing. 35 package bar 36 37 // Foo does a thing. 38 func Foo(wow int) int { 39 return 42 + wow 40 } 41 `), 42 } 43 44 var pullFiles = map[string][]byte{ 45 "qux.go": []byte(`package bar 46 47 func Qux() error { 48 return nil 49 } 50 `), 51 "zz_generated.wowza.go": []byte(`package bar 52 53 func Qux() error { 54 return nil 55 } 56 `), 57 } 58 59 type ghc struct { 60 genfile []byte 61 pr github.PullRequest 62 changes []github.PullRequestChange 63 oldComments []github.ReviewComment 64 comment github.DraftReview 65 } 66 67 func (g *ghc) GetPullRequestChanges(org, repo string, number int) ([]github.PullRequestChange, error) { 68 return g.changes, nil 69 } 70 71 func (g *ghc) CreateReview(org, repo string, number int, r github.DraftReview) error { 72 g.comment = r 73 return nil 74 } 75 76 func (g *ghc) ListPullRequestComments(org, repo string, number int) ([]github.ReviewComment, error) { 77 return g.oldComments, nil 78 } 79 80 func (g *ghc) GetFile(org, repo, filepath, commit string) ([]byte, error) { 81 return g.genfile, nil 82 } 83 84 func (g *ghc) GetPullRequest(org, repo string, number int) (*github.PullRequest, error) { 85 return &g.pr, nil 86 } 87 88 var e = &github.GenericCommentEvent{ 89 Action: github.GenericCommentActionCreated, 90 IssueState: "open", 91 Body: "/lint", 92 User: github.User{Login: "cjwagner"}, 93 Number: 42, 94 IsPR: true, 95 Repo: github.Repo{ 96 Owner: github.User{Login: "foo"}, 97 Name: "bar", 98 FullName: "foo/bar", 99 }, 100 } 101 102 func TestMinConfidence(t *testing.T) { 103 zero := float64(0) 104 half := 0.5 105 cases := []struct { 106 name string 107 golint plugins.Golint 108 expected float64 109 }{ 110 { 111 name: "nothing set", 112 expected: defaultConfidence, 113 }, 114 { 115 name: "no confidence set", 116 golint: plugins.Golint{}, 117 expected: defaultConfidence, 118 }, 119 { 120 name: "confidence set to zero", 121 golint: plugins.Golint{MinimumConfidence: &zero}, 122 expected: zero, 123 }, 124 { 125 name: "confidence set positive", 126 golint: plugins.Golint{MinimumConfidence: &half}, 127 expected: half, 128 }, 129 } 130 for _, tc := range cases { 131 t.Run(tc.name, func(t *testing.T) { 132 actual := minConfidence(tc.golint) 133 if actual != tc.expected { 134 t.Errorf("minimum confidence %f != expected %f", actual, tc.expected) 135 } 136 }) 137 } 138 } 139 140 func TestLintV2(t *testing.T) { 141 testLint(localgit.NewV2, t) 142 } 143 144 func testLint(clients localgit.Clients, t *testing.T) { 145 lg, c, err := clients() 146 if err != nil { 147 t.Fatalf("Making localgit: %v", err) 148 } 149 defer func() { 150 if err := lg.Clean(); err != nil { 151 t.Errorf("Cleaning up localgit: %v", err) 152 } 153 if err := c.Clean(); err != nil { 154 t.Errorf("Cleaning up client: %v", err) 155 } 156 }() 157 if err := lg.MakeFakeRepo("foo", "bar"); err != nil { 158 t.Fatalf("Making fake repo: %v", err) 159 } 160 if err := lg.AddCommit("foo", "bar", initialFiles); err != nil { 161 t.Fatalf("Adding initial commit: %v", err) 162 } 163 if err := lg.CheckoutNewBranch("foo", "bar", "pull/42/head"); err != nil { 164 t.Fatalf("Checking out pull branch: %v", err) 165 } 166 if err := lg.AddCommit("foo", "bar", pullFiles); err != nil { 167 t.Fatalf("Adding PR commit: %v", err) 168 } 169 170 gh := &ghc{ 171 genfile: []byte("file-prefix zz_generated"), 172 changes: []github.PullRequestChange{ 173 { 174 Filename: "qux.go", 175 Patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 176 }, 177 { 178 Filename: "zz_generated.wowza.go", 179 Patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux2() error {\n+ return nil\n+}", 180 }, 181 }, 182 } 183 if err := handle(0, gh, c, logrus.NewEntry(logrus.New()), e); err != nil { 184 t.Fatalf("Got error from handle: %v", err) 185 } 186 if len(gh.comment.Comments) != 2 { 187 t.Fatalf("Expected two comments, got %d: %v.", len(gh.comment.Comments), gh.comment.Comments) 188 } 189 for _, c := range gh.comment.Comments { 190 pos := c.Position 191 gh.oldComments = append(gh.oldComments, github.ReviewComment{ 192 Path: c.Path, 193 Position: &pos, 194 Body: c.Body, 195 }) 196 } 197 if err := handle(0, gh, c, logrus.NewEntry(logrus.New()), e); err != nil { 198 t.Fatalf("Got error from handle on second try: %v", err) 199 } 200 if len(gh.comment.Comments) != 0 { 201 t.Fatalf("Expected no comments, got %d: %v", len(gh.comment.Comments), gh.comment.Comments) 202 } 203 204 // Test that we limit comments. 205 badFileLines := []string{"package baz", ""} 206 for i := 0; i < maxComments+5; i++ { 207 badFileLines = append(badFileLines, fmt.Sprintf("type PublicType%d int", i)) 208 } 209 gh.changes = append(gh.changes, github.PullRequestChange{ 210 Filename: "baz.go", 211 Patch: fmt.Sprintf("@@ -0,0 +1,%d @@\n+%s", len(badFileLines), strings.Join(badFileLines, "\n+")), 212 }) 213 if err := lg.AddCommit("foo", "bar", map[string][]byte{"baz.go": []byte(strings.Join(badFileLines, "\n"))}); err != nil { 214 t.Fatalf("Adding PR commit: %v", err) 215 } 216 gh.oldComments = nil 217 if err := handle(0, gh, c, logrus.NewEntry(logrus.New()), e); err != nil { 218 t.Fatalf("Got error from handle on third try: %v", err) 219 } 220 if len(gh.comment.Comments) != maxComments { 221 t.Fatalf("Expected %d comments, got %d: %v", maxComments, len(gh.comment.Comments), gh.comment.Comments) 222 } 223 } 224 225 func TestLintCodeSuggestionV2(t *testing.T) { 226 testLintCodeSuggestion(localgit.NewV2, t) 227 } 228 229 func testLintCodeSuggestion(clients localgit.Clients, t *testing.T) { 230 var testcases = []struct { 231 name string 232 codeChange string 233 pullFiles map[string][]byte 234 comment string 235 }{ 236 { 237 name: "Check names with underscore", 238 codeChange: "@@ -0,0 +1,7 @@\n+// Package bar comment\n+package bar\n+\n+// Qux_1 comment\n+func Qux_1_Func() error {\n+ return nil\n+}", 239 pullFiles: map[string][]byte{ 240 "qux.go": []byte("// Package bar comment\npackage bar\n\n// Qux_1 comment\nfunc Qux_1() error {\n return nil\n}\n"), 241 }, 242 comment: "```suggestion\nfunc Qux1() error {\n```\nGolint naming: don't use underscores in Go names; func Qux_1 should be Qux1. [More info](http://golang.org/doc/effective_go.html#mixed-caps). <!-- golint -->", 243 }, 244 { 245 name: "Check names with all caps", 246 codeChange: "@@ -0,0 +1,7 @@\n+// Package bar comment\n+package bar\n+\n+// QUX_FUNC comment\n+func QUX_FUNC() error {\n+ return nil\n+}", 247 pullFiles: map[string][]byte{ 248 "qux.go": []byte("// Package bar comment\npackage bar\n\n// QUX_FUNC comment\nfunc QUX_FUNC() error {\n return nil\n}\n"), 249 }, 250 comment: "```suggestion\nfunc QuxFunc() error {\n```\nGolint naming: don't use ALL_CAPS in Go names; use CamelCase. [More info](https://golang.org/wiki/CodeReviewComments#mixed-caps). <!-- golint -->", 251 }, 252 { 253 name: "Correct function name", 254 codeChange: "@@ -0,0 +1,7 @@\n+// Package bar comment\n+package bar\n+\n+// QuxFunc comment\n+func QuxFunc() error {\n+ return nil\n+}", 255 pullFiles: map[string][]byte{ 256 "qux.go": []byte("// Package bar comment\npackage bar\n\n// QuxFunc comment\nfunc QuxFunc() error {\n return nil\n}\n"), 257 }, 258 comment: "", 259 }, 260 { 261 name: "Check stutter in function names", 262 codeChange: "@@ -0,0 +1,9 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+// BarFunc comment\n+func BarFunc() error {\n+ return nil\n+}", 263 pullFiles: map[string][]byte{ 264 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\n// BarFunc comment\nfunc BarFunc() error {\n return nil\n}"), 265 }, 266 comment: "```suggestion\nfunc Func() error {\n```\nGolint naming: func name will be used as bar.BarFunc by other packages, and that stutters; consider calling this Func. [More info](https://golang.org/wiki/CodeReviewComments#package-names). <!-- golint -->", 267 }, 268 { 269 name: "Check stutter in type names", 270 codeChange: "@@ -0,0 +1,8 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+// BarMaker comment\n+type BarMaker struct{}\n+", 271 pullFiles: map[string][]byte{ 272 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\n// BarMaker comment\ntype BarMaker struct{}\n"), 273 }, 274 comment: "```suggestion\ntype Maker struct{}\n```\nGolint naming: type name will be used as bar.BarMaker by other packages, and that stutters; consider calling this Maker. [More info](https://golang.org/wiki/CodeReviewComments#package-names). <!-- golint -->", 275 }, 276 { 277 name: "Check stutter: no stutter", 278 codeChange: "@@ -0,0 +1,8 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+// barMaker comment\n+type barMaker struct{}\n+", 279 pullFiles: map[string][]byte{ 280 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\n// barMaker comment\ntype barMaker struct{}\n"), 281 }, 282 comment: "", 283 }, 284 { 285 name: "Check errorf with errors", 286 codeChange: "@@ -0,0 +1,14 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+import (\n+ \"errors\"\n+ \"fmt\"\n+)\n+\n+func f(x int) error {\n+ return errors.New(fmt.Sprintf(\"something %d\", x))\n+}\n+", 287 pullFiles: map[string][]byte{ 288 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\nimport (\n \"errors\"\n \"fmt\"\n)\n\nfunc f(x int) error {\n return errors.New(fmt.Sprintf(\"something %d\", x))\n}\n"), 289 }, 290 comment: "```suggestion\n return fmt.Errorf(\"something %d\", x)\n```\nGolint errors: should replace errors.New(fmt.Sprintf(...)) with fmt.Errorf(...). <!-- golint -->", 291 }, 292 { 293 name: "Check errorf: no error", 294 codeChange: "@@ -0,0 +1,14 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+import (\n+ \"errors\"\n+ \"fmt\"\n+)\n+\n+func f(x int) error {\n+ return fmt.Errorf(\"something %!d(MISSING)\", x)\n+}\n+", 295 pullFiles: map[string][]byte{ 296 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\nimport (\n \"errors\"\n \"fmt\"\n)\n\nfunc f(x int) error { return fmt.Errorf(\"something %!d(MISSING)\", x)\n}\n"), 297 }, 298 comment: "", 299 }, 300 { 301 name: "Check loop range: omit values", 302 codeChange: "@@ -0,0 +1,10 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+func f() {\n+for _ = range m {\n+}\n+}\n+", 303 pullFiles: map[string][]byte{ 304 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\nfunc f() {\nfor _ = range m {\n}\n}\n"), 305 }, 306 comment: "```suggestion\nfor range m {\n```\nGolint range-loop: should omit values from range; this loop is equivalent to `for range ...`. <!-- golint -->", 307 }, 308 { 309 name: "Check loop range: omit two values", 310 codeChange: "@@ -0,0 +1,10 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+func f() {\n+for _, _ = range m {\n+}\n+}\n+", 311 pullFiles: map[string][]byte{ 312 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\nfunc f() {\nfor _, _ = range m {\n}\n}\n"), 313 }, 314 comment: "```suggestion\nfor range m {\n```\nGolint range-loop: should omit values from range; this loop is equivalent to `for range ...`. <!-- golint -->", 315 }, 316 { 317 name: "Check loop range: omit 2nd value with =", 318 codeChange: "@@ -0,0 +1,11 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+func f() {\n+var y = 0\n+for y, _ = range m {\n+}\n+}\n+", 319 pullFiles: map[string][]byte{ 320 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\nfunc f() {\nvar y = 0\nfor y, _ = range m {\n}\n}\n"), 321 }, 322 comment: "```suggestion\nfor y = range m {\n```\nGolint range-loop: should omit 2nd value from range; this loop is equivalent to `for y = range ...`. <!-- golint -->", 323 }, 324 { 325 name: "Check loop range: omit 2nd value with :=", 326 codeChange: "@@ -0,0 +1,10 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+func f() {\n+for y, _ := range m {\n+}\n+}\n+", 327 pullFiles: map[string][]byte{ 328 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\nfunc f() {\nfor y, _ := range m {\n}\n}\n"), 329 }, 330 comment: "```suggestion\nfor y := range m {\n```\nGolint range-loop: should omit 2nd value from range; this loop is equivalent to `for y := range ...`. <!-- golint -->", 331 }, 332 { 333 name: "Check loop range: no error", 334 codeChange: "@@ -0,0 +1,10 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+func f() {\n+for y := range m {\n+}\n+}\n+", 335 pullFiles: map[string][]byte{ 336 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\nfunc f() {\nfor y := range m {\n}\n}\n"), 337 }, 338 comment: "", 339 }, 340 { 341 name: "Check variable declaration: no value suggestion", 342 codeChange: "@@ -0,0 +1,9 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+func f() {\n+var myZeroRune2 rune\n+}\n+", 343 pullFiles: map[string][]byte{ 344 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\nfunc f() {\nvar myZeroRune2 rune\n}\n"), 345 }, 346 comment: "", 347 }, 348 { 349 name: "Check variable declaration: no type suggestion", 350 codeChange: "@@ -0,0 +1,9 @@\n+/*\n+Package bar comment\n+*/\n+package bar\n+\n+func f() {\n+var myInt = 7\n+}\n+", 351 pullFiles: map[string][]byte{ 352 "qux.go": []byte("/*\nPackage bar comment\n*/\npackage bar\n\nfunc f() {\nvar myInt = 7\n}\n"), 353 }, 354 comment: "", 355 }, 356 } 357 358 lg, c, err := clients() 359 if err != nil { 360 t.Fatalf("Making localgit: %v", err) 361 } 362 defer func() { 363 if err := lg.Clean(); err != nil { 364 t.Errorf("Cleaning up localgit: %v", err) 365 } 366 if err := c.Clean(); err != nil { 367 t.Errorf("Cleaning up client: %v", err) 368 } 369 }() 370 if err := lg.MakeFakeRepo("foo", "bar"); err != nil { 371 t.Fatalf("Making fake repo: %v", err) 372 } 373 if err := lg.AddCommit("foo", "bar", initialFiles); err != nil { 374 t.Fatalf("Adding initial commit: %v", err) 375 } 376 if err := lg.CheckoutNewBranch("foo", "bar", "pull/42/head"); err != nil { 377 t.Fatalf("Checking out pull branch: %v", err) 378 } 379 380 for _, test := range testcases { 381 t.Logf("Running test case %q...", test.name) 382 if err := lg.AddCommit("foo", "bar", test.pullFiles); err != nil { 383 t.Fatalf("Adding PR commit: %v", err) 384 } 385 gh := &ghc{ 386 changes: []github.PullRequestChange{ 387 { 388 Filename: "qux.go", 389 Patch: test.codeChange, 390 }, 391 }, 392 } 393 if err := handle(0, gh, c, logrus.NewEntry(logrus.New()), e); err != nil { 394 t.Fatalf("Got error from handle: %v", err) 395 } 396 397 if test.comment == "" { 398 if len(gh.comment.Comments) > 0 { 399 t.Fatalf("Expected no comment, got %d: %v.", len(gh.comment.Comments), gh.comment.Comments) 400 } 401 } else { 402 if len(gh.comment.Comments) != 1 { 403 t.Fatalf("Expected one comments, got %d: %v.", len(gh.comment.Comments), gh.comment.Comments) 404 } 405 if test.comment != gh.comment.Comments[0].Body { 406 t.Fatalf("Expected\n" + test.comment + "\n but got\n" + gh.comment.Comments[0].Body) 407 } 408 } 409 } 410 } 411 412 func TestLintErrorV2(t *testing.T) { 413 testLintError(localgit.NewV2, t) 414 } 415 416 func testLintError(clients localgit.Clients, t *testing.T) { 417 418 var testcases = []struct { 419 name string 420 codeChange string 421 pullFiles map[string][]byte 422 comments []github.DraftReviewComment 423 }{ 424 { 425 name: "Golint error", 426 codeChange: "@@ -0,0 +1,15 @@\n+" + 427 "/*\n+" + 428 "Package bar comment\n+" + 429 "*/\n+" + 430 "package bar\n+" + 431 "\n+" + 432 "func f(m []string) {\n+" + 433 " for _ = range m {\n+" + 434 " }\n+" + 435 "}\n+" + 436 "\n+" + 437 "for b() error {\n+" + 438 "return nil\n+" + 439 "}\n+", 440 pullFiles: map[string][]byte{ 441 "qux.go": []byte("/*\n" + 442 "Package bar comment\n" + 443 "*/\n" + 444 "package bar\n" + 445 "\n" + 446 "func f(m []string) {\n" + 447 " for _ = range m {\n" + 448 " }\n" + 449 "}\n" + 450 "\n" + 451 "for b() error {\n" + 452 "return nil\n" + 453 "}\n"), 454 }, 455 comments: []github.DraftReviewComment{ 456 { 457 Body: "expected declaration, found 'for'", 458 Position: 11, 459 Path: "qux.go", 460 }, 461 { 462 Body: "computing added lines in qux.go: invalid patch: " + 463 "@@ -0,0 +1,15 @@\n+" + 464 "/*\n+" + 465 "Package bar comment\n+" + 466 "*/\n+" + 467 "package bar\n+" + 468 "\n+" + 469 "func f(m []string) {\n+" + 470 " for _ = range m {\n+" + 471 " }\n+" + 472 "}\n+" + 473 "\n+" + 474 "for b() error {\n+" + 475 "return nil\n+" + 476 "}\n+", 477 Position: 0, 478 Path: "qux.go", 479 }, 480 }, 481 }, 482 { 483 name: "No golint error", 484 codeChange: "@@ -0,0 +1,9 @@\n+" + 485 "/*\n+" + 486 "Package bar comment\n+" + 487 "*/\n+" + 488 "package bar\n+" + 489 "\n+" + 490 "func f() {\n+" + 491 " var myZeroFlt float32 = 0.\n+" + 492 "}\n+", 493 pullFiles: map[string][]byte{ 494 "qux.go": []byte("/*\n" + 495 "Package bar comment\n" + 496 "*/\n" + 497 "package bar\n" + 498 "\n" + 499 "func b() error {\n" + 500 "return nil\n" + 501 "}\n"), 502 }, 503 comments: nil, 504 }, 505 } 506 507 lg, c, err := clients() 508 if err != nil { 509 t.Fatalf("Making localgit: %v", err) 510 } 511 defer func() { 512 if err := lg.Clean(); err != nil { 513 t.Errorf("Cleaning up localgit: %v", err) 514 } 515 if err := c.Clean(); err != nil { 516 t.Errorf("Cleaning up client: %v", err) 517 } 518 }() 519 if err := lg.MakeFakeRepo("foo", "bar"); err != nil { 520 t.Fatalf("Making fake repo: %v", err) 521 } 522 if err := lg.AddCommit("foo", "bar", initialFiles); err != nil { 523 t.Fatalf("Adding initial commit: %v", err) 524 } 525 if err := lg.CheckoutNewBranch("foo", "bar", "pull/42/head"); err != nil { 526 t.Fatalf("Checking out pull branch: %v", err) 527 } 528 529 for _, test := range testcases { 530 t.Logf("Running test case %q...", test.name) 531 if err := lg.AddCommit("foo", "bar", test.pullFiles); err != nil { 532 t.Fatalf("Adding PR commit: %v", err) 533 } 534 gh := &ghc{ 535 changes: []github.PullRequestChange{ 536 { 537 Filename: "qux.go", 538 Patch: test.codeChange, 539 }, 540 }, 541 } 542 if err := handle(0, gh, c, logrus.NewEntry(logrus.New()), e); err != nil { 543 t.Fatalf("Got error from handle: %v", err) 544 } 545 546 if test.comments == nil { 547 if len(gh.comment.Comments) > 0 { 548 t.Fatalf("Expected no comment, got %d: %v.", len(gh.comment.Comments), gh.comment.Comments) 549 } 550 } else { 551 if len(gh.comment.Comments) != len(test.comments) { 552 t.Fatalf("Expected one comments, got %d: %v.", len(gh.comment.Comments), gh.comment.Comments) 553 } 554 for _, testComment := range test.comments { 555 exists := false 556 for _, actualComment := range gh.comment.Comments { 557 if actualComment == testComment { 558 exists = true 559 } 560 } 561 if !exists { 562 t.Fatalf("Did not get back expected comment %v, actual comments are %v", testComment, gh.comment.Comments) 563 } 564 } 565 } 566 } 567 } 568 569 func TestAddedLines(t *testing.T) { 570 var testcases = []struct { 571 patch string 572 lines map[int]int 573 err bool 574 }{ 575 { 576 patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 577 lines: map[int]int{1: 1, 2: 2, 3: 3, 4: 4, 5: 5}, 578 }, 579 { 580 patch: "@@ -29,12 +29,14 @@ import (\n \t\"github.com/sirupsen/logrus\"\n \t\"sigs.k8s.io/yaml\"\n \n+\t\"sigs.k8s.io/prow/pkg/config\"\n \t\"sigs.k8s.io/prow/pkg/jenkins\"\n \t\"sigs.k8s.io/prow/pkg/kube\"\n \t\"sigs.k8s.io/prow/pkg/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}", 581 lines: map[int]int{4: 32, 11: 39, 23: 54, 24: 55, 25: 56, 26: 57, 27: 58, 28: 59, 35: 65, 38: 67}, 582 }, 583 { 584 patch: "@@ -1 +0,0 @@\n-such", 585 }, 586 { 587 patch: "@@ -1,3 +0,0 @@\n-such\n-a\n-doge", 588 }, 589 { 590 patch: "@@ -0,0 +1 @@\n+wow", 591 lines: map[int]int{1: 1}, 592 }, 593 { 594 patch: "@@ -0,0 +1 @@\n+wow\n\\ No newline at end of file", 595 lines: map[int]int{1: 1}, 596 }, 597 { 598 patch: "@@ -1 +1 @@\n-doge\n+wow", 599 lines: map[int]int{2: 1}, 600 }, 601 { 602 patch: "something strange", 603 err: true, 604 }, 605 { 606 patch: "@@ -a,3 +0,0 @@\n-wow", 607 err: true, 608 }, 609 { 610 patch: "@@ -1 +1 @@", 611 err: true, 612 }, 613 { 614 patch: "", 615 }, 616 } 617 for _, tc := range testcases { 618 als, err := AddedLines(tc.patch) 619 if err == nil == tc.err { 620 t.Errorf("For patch %s\nExpected error %v, got error %v", tc.patch, tc.err, err) 621 continue 622 } 623 if len(als) != len(tc.lines) { 624 t.Errorf("For patch %s\nAdded lines has wrong length. Got %v, expected %v", tc.patch, als, tc.lines) 625 } 626 for pl, l := range tc.lines { 627 if als[l] != pl { 628 t.Errorf("For patch %s\nExpected added line %d to be %d, but got %d", tc.patch, l, pl, als[l]) 629 } 630 } 631 } 632 } 633 634 func TestModifiedGoFilesV2(t *testing.T) { 635 testModifiedGoFiles(localgit.NewV2, t) 636 } 637 638 func testModifiedGoFiles(clients localgit.Clients, t *testing.T) { 639 lg, c, err := clients() 640 if err != nil { 641 t.Fatalf("Making localgit: %v", err) 642 } 643 defer func() { 644 if err := lg.Clean(); err != nil { 645 t.Errorf("Cleaning up localgit: %v", err) 646 } 647 if err := c.Clean(); err != nil { 648 t.Errorf("Cleaning up client: %v", err) 649 } 650 }() 651 if err := lg.MakeFakeRepo("foo", "bar"); err != nil { 652 t.Fatalf("Making fake repo: %v", err) 653 } 654 if err := lg.AddCommit("foo", "bar", initialFiles); err != nil { 655 t.Fatalf("Adding initial commit: %v", err) 656 } 657 if err := lg.CheckoutNewBranch("foo", "bar", "pull/42/head"); err != nil { 658 t.Fatalf("Checking out pull branch: %v", err) 659 } 660 if err := lg.AddCommit("foo", "bar", pullFiles); err != nil { 661 t.Fatalf("Adding PR commit: %v", err) 662 } 663 664 var testcases = []struct { 665 name string 666 gh *ghc 667 expectedModifiedFiles map[string]string 668 }{ 669 { 670 name: "modified files include vendor file", 671 gh: &ghc{ 672 changes: []github.PullRequestChange{ 673 { 674 Filename: "qux.go", 675 Patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 676 }, 677 { 678 Filename: "vendor/foo/bar.go", 679 Patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux2() error {\n+ return nil\n+}", 680 }, 681 }, 682 }, 683 expectedModifiedFiles: map[string]string{ 684 "qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 685 }, 686 }, 687 { 688 name: "modified files include non go file", 689 gh: &ghc{ 690 changes: []github.PullRequestChange{ 691 { 692 Filename: "qux.go", 693 Patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 694 }, 695 { 696 Filename: "foo.md", 697 Patch: "@@ -1,3 +1,4 @@\n+TODO", 698 }, 699 }, 700 }, 701 expectedModifiedFiles: map[string]string{ 702 "qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 703 }, 704 }, 705 { 706 name: "modified files include generated file", 707 gh: &ghc{ 708 genfile: []byte("file-prefix zz_generated"), 709 changes: []github.PullRequestChange{ 710 { 711 Filename: "qux.go", 712 Patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 713 }, 714 { 715 Filename: "zz_generated.wowza.go", 716 Patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux2() error {\n+ return nil\n+}", 717 }, 718 }, 719 }, 720 expectedModifiedFiles: map[string]string{ 721 "qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 722 }, 723 }, 724 { 725 name: "modified files include removed file", 726 gh: &ghc{ 727 changes: []github.PullRequestChange{ 728 { 729 Filename: "qux.go", 730 Patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 731 }, 732 { 733 Filename: "bar.go", 734 Status: github.PullRequestFileRemoved, 735 Patch: "@@ -1,5 +0,0 @@\n-package bar\n-\n-func Qux() error {\n- return nil\n-}", 736 }, 737 }, 738 }, 739 expectedModifiedFiles: map[string]string{ 740 "qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 741 }, 742 }, 743 { 744 name: "modified files include renamed file", 745 gh: &ghc{ 746 changes: []github.PullRequestChange{ 747 { 748 Filename: "qux.go", 749 Patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 750 }, 751 { 752 Filename: "bar.go", 753 Status: github.PullRequestFileRenamed, 754 }, 755 }, 756 }, 757 expectedModifiedFiles: map[string]string{ 758 "qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 759 }, 760 }, 761 { 762 name: "added and modified files", 763 gh: &ghc{ 764 changes: []github.PullRequestChange{ 765 { 766 Filename: "qux.go", 767 Status: github.PullRequestFileAdded, 768 Patch: "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 769 }, 770 { 771 Filename: "bar.go", 772 Patch: "@@ -0,0 +1,5 @@\n+package baz\n+\n+func Bar() error {\n+ return nil\n+}", 773 }, 774 }, 775 }, 776 expectedModifiedFiles: map[string]string{ 777 "qux.go": "@@ -0,0 +1,5 @@\n+package bar\n+\n+func Qux() error {\n+ return nil\n+}", 778 "bar.go": "@@ -0,0 +1,5 @@\n+package baz\n+\n+func Bar() error {\n+ return nil\n+}", 779 }, 780 }, 781 { 782 name: "removed and renamed files", 783 gh: &ghc{ 784 changes: []github.PullRequestChange{ 785 { 786 Filename: "qux.go", 787 Status: github.PullRequestFileRemoved, 788 Patch: "@@ -1,5 +0,0 @@\n-package bar\n-\n-func Qux() error {\n- return nil\n-}", 789 }, 790 { 791 Filename: "bar.go", 792 Status: github.PullRequestFileRenamed, 793 }, 794 }, 795 }, 796 expectedModifiedFiles: map[string]string{}, 797 }, 798 } 799 for _, tc := range testcases { 800 actualModifiedFiles, _ := modifiedGoFiles(tc.gh, "foo", "bar", 9527, "0ebb33b") 801 if !reflect.DeepEqual(tc.expectedModifiedFiles, actualModifiedFiles) { 802 t.Errorf("Expected: %#v, Got %#v in case %s.", tc.expectedModifiedFiles, actualModifiedFiles, tc.name) 803 } 804 } 805 } 806 807 func TestHelpProvider(t *testing.T) { 808 half := 0.5 809 enabledRepos := []config.OrgRepo{ 810 {Org: "org1", Repo: "repo"}, 811 {Org: "org2", Repo: "repo"}, 812 } 813 cases := []struct { 814 name string 815 config *plugins.Configuration 816 enabledRepos []config.OrgRepo 817 err bool 818 }{ 819 { 820 name: "Empty config", 821 config: &plugins.Configuration{}, 822 enabledRepos: enabledRepos, 823 }, 824 { 825 name: "MinimumConfidence specified", 826 config: &plugins.Configuration{ 827 Golint: plugins.Golint{ 828 MinimumConfidence: &half, 829 }, 830 }, 831 enabledRepos: enabledRepos, 832 }, 833 } 834 for _, c := range cases { 835 t.Run(c.name, func(t *testing.T) { 836 _, err := helpProvider(c.config, c.enabledRepos) 837 if err != nil && !c.err { 838 t.Fatalf("helpProvider error: %v", err) 839 } 840 }) 841 } 842 }