github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/prow/plugins/slackevents/slackevents_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 slackevents
    18  
    19  import (
    20  	"encoding/json"
    21  	"strings"
    22  	"testing"
    23  
    24  	"k8s.io/test-infra/prow/github"
    25  	"k8s.io/test-infra/prow/github/fakegithub"
    26  	"k8s.io/test-infra/prow/plugins"
    27  	"k8s.io/test-infra/prow/slack"
    28  )
    29  
    30  type FakeClient struct {
    31  	SentMessages map[string][]string
    32  }
    33  
    34  func (fk *FakeClient) WriteMessage(text string, channel string) error {
    35  	fk.SentMessages[channel] = append(fk.SentMessages[channel], text)
    36  	return nil
    37  }
    38  
    39  func TestPush(t *testing.T) {
    40  	var pushStr = `{
    41    "ref": "refs/heads/master",
    42    "before": "d73a75b4b1ddb63870954b9a60a63acaa4cb1ca5",
    43    "after": "045a6dca07840efaf3311450b615e19b5c75f787",
    44    "created": false,
    45    "deleted": false,
    46    "forced": false,
    47    "compare": "https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784",
    48    "commits": [
    49      {
    50        "id": "8427d5a27478c80167fd66affe1bd7cd01d3f9a8",
    51        "message": "Decrease fluentd cpu request",
    52        "url": "https://github.com/kubernetes/kubernetes/commit/8427d5a27478c80167fd66affe1bd7cd01d3f9a8"
    53      },
    54      {
    55        "id": "045a6dca07840efaf3311450b615e19b5c75f787",
    56        "message": "Merge pull request #47906 from gmarek/fluentd\n\nDecrese fluentd cpu request\n\nFix #47905\r\n\r\ncc @piosz - this should fix your tests.\r\ncc @dchen1107",
    57        "url": "https://github.com/kubernetes/kubernetes/commit/045a6dca07840efaf3311450b615e19b5c75f787"
    58      }
    59    ],
    60    "repository": {
    61      "id": 20580498,
    62      "name": "kubernetes",
    63      "owner": {
    64  	"name": "kubernetes",
    65  	"login": "kubernetes"
    66      },
    67      "url": "https://github.com/kubernetes/kubernetes"
    68    },
    69    "pusher": {
    70      "name": "k8s-merge-robot",
    71      "email": "k8s-merge-robot@users.noreply.github.com"
    72    }
    73  }`
    74  
    75  	var pushEv github.PushEvent
    76  	if err := json.Unmarshal([]byte(pushStr), &pushEv); err != nil {
    77  		t.Fatalf("Failed to parse Push Notification: %s", err)
    78  	}
    79  
    80  	// Non bot user merged the PR
    81  	pushEvManual := pushEv
    82  	pushEvManual.Pusher.Name = "Jester Tester"
    83  	pushEvManual.Pusher.Email = "tester@users.noreply.github.com"
    84  	pushEvManual.Sender.Login = "tester"
    85  	pushEvManual.Ref = "refs/head/master"
    86  
    87  	pushEvManualBranchWhiteListed := pushEv
    88  	pushEvManualBranchWhiteListed.Pusher.Name = "Warren Teened"
    89  	pushEvManualBranchWhiteListed.Pusher.Email = "wteened@users.noreply.github.com"
    90  	pushEvManualBranchWhiteListed.Sender.Login = "wteened"
    91  	pushEvManualBranchWhiteListed.Ref = "refs/head/warrens-branch"
    92  
    93  	pushEvManualNotBranchWhiteListed := pushEvManualBranchWhiteListed
    94  	pushEvManualNotBranchWhiteListed.Ref = "refs/head/master"
    95  
    96  	pushEvManualCreated := pushEvManual
    97  	pushEvManualCreated.Created = true
    98  	pushEvManualCreated.Ref = "refs/head/release-1.99"
    99  	pushEvManualCreated.Compare = "https://github.com/kubernetes/kubernetes/compare/045a6dca0784"
   100  
   101  	pushEvManualDeleted := pushEvManual
   102  	pushEvManualDeleted.Deleted = true
   103  	pushEvManualDeleted.Ref = "refs/head/release-1.99"
   104  	pushEvManualDeleted.Compare = "https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...000000000000"
   105  
   106  	pushEvManualForced := pushEvManual
   107  	pushEvManualForced.Forced = true
   108  
   109  	noMessages := map[string][]string{}
   110  	stdWarningMessages := map[string][]string{
   111  		"sig-contribex":  {"*Warning:* tester (<@tester>) manually merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"},
   112  		"kubernetes-dev": {"*Warning:* tester (<@tester>) manually merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"}}
   113  
   114  	createdWarningMessages := map[string][]string{
   115  		"sig-contribex":  {"*Warning:* tester (<@tester>) pushed a new branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/045a6dca0784"},
   116  		"kubernetes-dev": {"*Warning:* tester (<@tester>) pushed a new branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/045a6dca0784"}}
   117  
   118  	deletedWarningMessages := map[string][]string{
   119  		"sig-contribex":  {"*Warning:* tester (<@tester>) deleted a branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...000000000000"},
   120  		"kubernetes-dev": {"*Warning:* tester (<@tester>) deleted a branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...000000000000"}}
   121  
   122  	forcedWarningMessages := map[string][]string{
   123  		"sig-contribex":  {"*Warning:* tester (<@tester>) *force* merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"},
   124  		"kubernetes-dev": {"*Warning:* tester (<@tester>) *force* merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"}}
   125  
   126  	type testCase struct {
   127  		name             string
   128  		pushReq          github.PushEvent
   129  		expectedMessages map[string][]string
   130  	}
   131  
   132  	testcases := []testCase{
   133  		{
   134  			name:             "If PR merged manually by a user, we send message to sig-contribex and kubernetes-dev.",
   135  			pushReq:          pushEvManual,
   136  			expectedMessages: stdWarningMessages,
   137  		},
   138  		{
   139  			name:             "If PR force merged by a user, we send message to sig-contribex and kubernetes-dev with force merge message.",
   140  			pushReq:          pushEvManualForced,
   141  			expectedMessages: forcedWarningMessages,
   142  		},
   143  		{
   144  			name:             "If PR merged by k8s merge bot we should NOT send message to sig-contribex and kubernetes-dev.",
   145  			pushReq:          pushEv,
   146  			expectedMessages: noMessages,
   147  		},
   148  		{
   149  			name:             "If PR merged by a user not in the whitelist but in THIS branch whitelist, we should NOT send a message to sig-contrib-ax and kubernetes-dev.",
   150  			pushReq:          pushEvManualBranchWhiteListed,
   151  			expectedMessages: noMessages,
   152  		},
   153  		{
   154  			name:             "If PR merged by a user not in the whitelist, in a branch whitelist, but not THIS branch whitelist, we should send a message to sig-contrib-ax and kubernetes-dev.",
   155  			pushReq:          pushEvManualBranchWhiteListed,
   156  			expectedMessages: noMessages,
   157  		},
   158  		{
   159  			name:             "If a branch is created by a non-whitelisted user, we send message to sig-contribex and kubernetes-dev with branch created message.",
   160  			pushReq:          pushEvManualCreated,
   161  			expectedMessages: createdWarningMessages,
   162  		},
   163  		{
   164  			name:             "If a branch is deleted by a non-whitelisted user, we send message to sig-contribex and kubernetes-dev with branch deleted message.",
   165  			pushReq:          pushEvManualDeleted,
   166  			expectedMessages: deletedWarningMessages,
   167  		},
   168  	}
   169  
   170  	pc := client{
   171  		SlackConfig: plugins.Slack{
   172  			MergeWarnings: []plugins.MergeWarning{
   173  				{
   174  					Repos:     []string{"kubernetes/kubernetes"},
   175  					Channels:  []string{"kubernetes-dev", "sig-contribex"},
   176  					WhiteList: []string{"k8s-merge-robot"},
   177  					BranchWhiteList: map[string][]string{
   178  						"warrens-branch": {"wteened"},
   179  					},
   180  				},
   181  			},
   182  		},
   183  		SlackClient: slack.NewFakeClient(),
   184  	}
   185  
   186  	//should not fail if slackClient is nil
   187  	for _, tc := range testcases {
   188  		if err := notifyOnSlackIfManualMerge(pc, tc.pushReq); err != nil {
   189  			t.Fatalf("Didn't expect error if slack client is nil: %s", err)
   190  		}
   191  	}
   192  
   193  	//repeat the tests with a fake slack client
   194  	for _, tc := range testcases {
   195  		slackClient := &FakeClient{
   196  			SentMessages: make(map[string][]string),
   197  		}
   198  		pc.SlackClient = slackClient
   199  
   200  		if err := notifyOnSlackIfManualMerge(pc, tc.pushReq); err != nil {
   201  			t.Fatalf("Didn't expect error: %s", err)
   202  		}
   203  		if len(tc.expectedMessages) != len(slackClient.SentMessages) {
   204  			t.Fatalf("Test: %s The number of messages sent do not tally. Expecting %d messages but received %d messages.",
   205  				tc.name, len(tc.expectedMessages), len(slackClient.SentMessages))
   206  		}
   207  		for k, v := range tc.expectedMessages {
   208  			if _, ok := slackClient.SentMessages[k]; !ok {
   209  				t.Fatalf("Test: %s Messages is not sent to channel %s", tc.name, k)
   210  			}
   211  			if strings.Compare(v[0], slackClient.SentMessages[k][0]) != 0 {
   212  				t.Fatalf("Expecting message: %s\nReceived message: %s", v, slackClient.SentMessages[k])
   213  			}
   214  			if len(v) != len(slackClient.SentMessages[k]) {
   215  				t.Fatalf("Test: %s All messages are not delivered to the channel ", tc.name)
   216  			}
   217  		}
   218  	}
   219  
   220  }
   221  
   222  //Make sure we are sending message to proper sig mentions
   223  func TestComment(t *testing.T) {
   224  	orgMember := "cjwagner"
   225  	bot := "k8s-ci-robot"
   226  	type testCase struct {
   227  		name             string
   228  		action           github.GenericCommentEventAction
   229  		body             string
   230  		expectedMessages map[string][]string
   231  		issueLabels      []string
   232  		repoLabels       []string
   233  		commenter        string
   234  	}
   235  	testcases := []testCase{
   236  		{
   237  			name:             "If sig mentioned then we send a message to the sig with the body of the comment",
   238  			action:           github.GenericCommentActionCreated,
   239  			body:             "@kubernetes/sig-node-misc This issue needs update.",
   240  			expectedMessages: map[string][]string{"sig-node": {"This issue needs update."}},
   241  			commenter:        orgMember,
   242  		},
   243  		{
   244  			name:             "Don't sent message if comment isn't new.",
   245  			action:           github.GenericCommentActionEdited,
   246  			body:             "@kubernetes/sig-node-misc This issue needs update.",
   247  			expectedMessages: map[string][]string{},
   248  			commenter:        orgMember,
   249  		},
   250  		{
   251  			name:             "Don't sent message if commenter is the bot.",
   252  			action:           github.GenericCommentActionEdited,
   253  			body:             "@kubernetes/sig-node-misc This issue needs update.",
   254  			expectedMessages: map[string][]string{},
   255  			commenter:        bot,
   256  		},
   257  		{
   258  			name:             "If multiple sigs mentioned, we send a message to each sig with the body of the comment",
   259  			action:           github.GenericCommentActionCreated,
   260  			body:             "@kubernetes/sig-node-misc, @kubernetes/sig-api-machinery-misc Message sent to multiple sigs.",
   261  			expectedMessages: map[string][]string{"sig-api-machinery": {"Message sent to multiple sigs."}, "sig-node": {"Message sent to multiple sigs."}},
   262  			commenter:        orgMember,
   263  		},
   264  		{
   265  			name:             "If multiple sigs mentioned, but only one channel is whitelisted, only send to one channel.",
   266  			action:           github.GenericCommentActionCreated,
   267  			body:             "@kubernetes/sig-node-misc, @kubernetes/sig-testing-misc Message sent to multiple sigs.",
   268  			expectedMessages: map[string][]string{"sig-node": {"Message sent to multiple sigs."}},
   269  			issueLabels:      []string{},
   270  			commenter:        orgMember,
   271  		},
   272  		{
   273  			name:             "Message should not be sent if the pattern for the channel does not match",
   274  			action:           github.GenericCommentActionCreated,
   275  			body:             "@kubernetes/node-misc No message sent",
   276  			expectedMessages: map[string][]string{},
   277  			commenter:        orgMember,
   278  		},
   279  		{
   280  			name:             "Message sent only if the pattern for the channel match",
   281  			action:           github.GenericCommentActionCreated,
   282  			body:             "@kubernetes/node-misc @kubernetes/sig-api-machinery-bugs Message sent to matching sigs.",
   283  			expectedMessages: map[string][]string{"sig-api-machinery": {"Message sent to matching sigs."}},
   284  			commenter:        orgMember,
   285  		},
   286  	}
   287  
   288  	for _, tc := range testcases {
   289  		fakeSlackClient := &FakeClient{
   290  			SentMessages: make(map[string][]string),
   291  		}
   292  		client := client{
   293  			GithubClient: &fakegithub.FakeClient{},
   294  			SlackClient:  fakeSlackClient,
   295  			SlackConfig:  plugins.Slack{MentionChannels: []string{"sig-node", "sig-api-machinery"}},
   296  		}
   297  		e := github.GenericCommentEvent{
   298  			Action: tc.action,
   299  			Body:   tc.body,
   300  			User:   github.User{Login: tc.commenter},
   301  		}
   302  
   303  		if err := echoToSlack(client, e); err != nil {
   304  			t.Fatalf("For case %s, didn't expect error from label test: %v", tc.name, err)
   305  		}
   306  		if len(tc.expectedMessages) != len(fakeSlackClient.SentMessages) {
   307  			t.Fatalf("The number of messages sent do not tally. Expecting %d messages but received %d messages.",
   308  				len(tc.expectedMessages), len(fakeSlackClient.SentMessages))
   309  		}
   310  		for k, v := range tc.expectedMessages {
   311  			if _, ok := fakeSlackClient.SentMessages[k]; !ok {
   312  				t.Fatalf("Messages is not sent to channel %s", k)
   313  			}
   314  			if len(v) != len(fakeSlackClient.SentMessages[k]) {
   315  				t.Fatalf("All messages are not delivered to the channel %s", k)
   316  			}
   317  		}
   318  	}
   319  }