blob: faaedcac95da75d4697c2ee5b8d62ea5bfb025c1 [file] [log] [blame]
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"context"
"net/http"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/google/go-github/github"
"golang.org/x/build/maintner"
)
func TestLabelCommandsFromComments(t *testing.T) {
created := time.Now()
testCases := []struct {
desc string
body string
cmds []labelCommand
}{
{
"basic add/remove",
"We should fix this issue, but we need help\n\n@gopherbot please add help wanted, needsfix and remove needsinvestigation",
[]labelCommand{
{action: "add", label: "help wanted", created: created},
{action: "add", label: "needsfix", created: created},
{action: "remove", label: "needsinvestigation", created: created},
},
},
{
"no please",
"@gopherbot add NeedsFix",
[]labelCommand{
{action: "add", label: "needsfix", created: created},
},
},
{
"with comma",
"@gopherbot, NeedsFix",
[]labelCommand{
{action: "add", label: "needsfix", created: created},
},
},
{
"with semicolons",
"@gopherbot NeedsFix;help wanted; remove needsinvestigation",
[]labelCommand{
{action: "add", label: "needsfix", created: created},
{action: "add", label: "help wanted", created: created},
{action: "remove", label: "needsinvestigation", created: created},
},
},
{
"case insensitive",
"@gopherbot please add HelP WanteD",
[]labelCommand{
{action: "add", label: "help wanted", created: created},
},
},
{
"fun input",
"@gopherbot please add help wanted,;needsfix;",
[]labelCommand{
{action: "add", label: "help wanted", created: created},
{action: "add", label: "needsfix", created: created},
},
},
{
"with hyphen",
"@gopherbot please add label OS-macOS",
[]labelCommand{
{action: "add", label: "os-macos", created: created},
},
},
{
"unlabel keyword",
"@gopherbot please unlabel needsinvestigation, NeedsDecision",
[]labelCommand{
{action: "remove", label: "needsinvestigation", created: created},
{action: "remove", label: "needsdecision", created: created},
},
},
{
"with label[s] keyword",
"@gopherbot please add label help wanted and remove labels needsinvestigation, NeedsDecision",
[]labelCommand{
{action: "add", label: "help wanted", created: created},
{action: "remove", label: "needsinvestigation", created: created},
{action: "remove", label: "needsdecision", created: created},
},
},
{
"no label commands",
"The cake was a lie",
nil,
},
}
for _, tc := range testCases {
cmds := labelCommandsFromBody(tc.body, created)
if diff := cmp.Diff(cmds, tc.cmds, cmp.AllowUnexported(labelCommand{})); diff != "" {
t.Errorf("%s: commands differ: (-got +want)\n%s", tc.desc, diff)
}
}
}
func TestLabelMutations(t *testing.T) {
testCases := []struct {
desc string
cmds []labelCommand
add []string
remove []string
}{
{
"basic",
[]labelCommand{
{action: "add", label: "foo"},
{action: "remove", label: "baz"},
},
[]string{"foo"},
[]string{"baz"},
},
{
"add/remove of same label",
[]labelCommand{
{action: "add", label: "foo"},
{action: "remove", label: "foo"},
{action: "remove", label: "bar"},
{action: "add", label: "bar"},
},
nil,
nil,
},
{
"deduplication of labels",
[]labelCommand{
{action: "add", label: "foo"},
{action: "add", label: "foo"},
{action: "remove", label: "bar"},
{action: "remove", label: "bar"},
},
[]string{"foo"},
[]string{"bar"},
},
{
"forbidden actions",
[]labelCommand{
{action: "add", label: "Proposal-Accepted"},
{action: "add", label: "CherryPickApproved"},
{action: "add", label: "cla: yes"},
{action: "remove", label: "Security"},
},
nil,
nil,
},
{
"can add Security",
[]labelCommand{
{action: "add", label: "Security"},
},
[]string{"Security"},
nil,
},
}
for _, tc := range testCases {
add, remove := mutationsFromCommands(tc.cmds)
if diff := cmp.Diff(add, tc.add); diff != "" {
t.Errorf("%s: label additions differ: (-got, +want)\n%s", tc.desc, diff)
}
if diff := cmp.Diff(remove, tc.remove); diff != "" {
t.Errorf("%s: label removals differ: (-got, +want)\n%s", tc.desc, diff)
}
}
}
func TestAddLabels(t *testing.T) {
oldFunc := addLabelsToIssue
defer func() { addLabelsToIssue = oldFunc }()
var added []string
addLabelsToIssue = func(_ context.Context, _ *github.IssuesService, _ int, labels []string) error {
added = labels
return nil
}
testCases := []struct {
desc string
gi *maintner.GitHubIssue
labels []string
added []string
}{
{
"basic add",
&maintner.GitHubIssue{},
[]string{"foo"},
[]string{"foo"},
},
{
"some labels already present in maintner",
&maintner.GitHubIssue{
Labels: map[int64]*maintner.GitHubLabel{
0: &maintner.GitHubLabel{Name: "NeedsDecision"},
},
},
[]string{"foo", "NeedsDecision"},
[]string{"foo"},
},
{
"all labels already present in maintner",
&maintner.GitHubIssue{
Labels: map[int64]*maintner.GitHubLabel{
0: &maintner.GitHubLabel{Name: "NeedsDecision"},
},
},
[]string{"NeedsDecision"},
nil,
},
}
b := &gopherbot{ghc: github.NewClient(http.DefaultClient)}
for _, tc := range testCases {
// Clear any previous state from stubbed addLabelsToIssue function above
// since some test cases may skip calls to it.
added = nil
if err := b.addLabels(nil, tc.gi, tc.labels); err != nil {
t.Errorf("%s: b.addLabels got unexpected error: %v", tc.desc, err)
continue
}
if diff := cmp.Diff(added, tc.added); diff != "" {
t.Errorf("%s: labels added differ: (-got, +want)\n%s", tc.desc, diff)
}
}
}
func TestRemoveLabels(t *testing.T) {
oldLabelsForIssue := labelsForIssue
defer func() { labelsForIssue = oldLabelsForIssue }()
labelsForIssue = func(_ context.Context, _ *github.IssuesService, _ int) ([]string, error) {
return []string{"help wanted", "NeedsFix"}, nil
}
oldRemoveLabelFromIssue := removeLabelFromIssue
defer func() { removeLabelFromIssue = oldRemoveLabelFromIssue }()
var removed []string
removeLabelFromIssue = func(_ context.Context, _ *github.IssuesService, _ int, label string) error {
removed = append(removed, label)
return nil
}
testCases := []struct {
desc string
gi *maintner.GitHubIssue
toRemove []string
removed []string
}{
{
"basic remove",
&maintner.GitHubIssue{
Labels: map[int64]*maintner.GitHubLabel{
0: &maintner.GitHubLabel{Name: "NeedsFix"},
},
},
[]string{"NeedsFix"},
[]string{"NeedsFix"},
},
{
"label not present in maintner",
&maintner.GitHubIssue{},
[]string{"NeedsFix"},
nil,
},
{
"label not present in GitHub",
&maintner.GitHubIssue{
Labels: map[int64]*maintner.GitHubLabel{
0: &maintner.GitHubLabel{Name: "foo"},
},
},
[]string{"foo"},
nil,
},
}
b := &gopherbot{ghc: github.NewClient(http.DefaultClient)}
for _, tc := range testCases {
// Clear any previous state from stubbed removeLabelFromIssue function above
// since some test cases may skip calls to it.
removed = nil
if err := b.removeLabels(nil, tc.gi, tc.toRemove); err != nil {
t.Errorf("%s: b.addLabels got unexpected error: %v", tc.desc, err)
continue
}
if diff := cmp.Diff(removed, tc.removed); diff != "" {
t.Errorf("%s: labels removed differ: (-got, +want)\n%s", tc.desc, diff)
}
}
}