<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package slackevents

import (
	"encoding/json"
	"strings"
	"testing"

	"k8s.io/test-infra/prow/config"
	"k8s.io/test-infra/prow/github"
	"k8s.io/test-infra/prow/github/fakegithub"
	"k8s.io/test-infra/prow/plugins"
	"k8s.io/test-infra/prow/slack"
)

type FakeClient struct {
	SentMessages map[string][]string
}

func (fk *FakeClient) WriteMessage(text string, channel string) error {
	fk.SentMessages[channel] = append(fk.SentMessages[channel], text)
	return nil
}

func TestPush(t *testing.T) {
	var pushStr = `{
  "ref": "refs/heads/master",
  "before": "d73a75b4b1ddb63870954b9a60a63acaa4cb1ca5",
  "after": "045a6dca07840efaf3311450b615e19b5c75f787",
  "created": false,
  "deleted": false,
  "forced": false,
  "compare": "https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784",
  "commits": [
    {
      "id": "8427d5a27478c80167fd66affe1bd7cd01d3f9a8",
      "message": "Decrease fluentd cpu request",
      "url": "https://github.com/kubernetes/kubernetes/commit/8427d5a27478c80167fd66affe1bd7cd01d3f9a8"
    },
    {
      "id": "045a6dca07840efaf3311450b615e19b5c75f787",
      "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",
      "url": "https://github.com/kubernetes/kubernetes/commit/045a6dca07840efaf3311450b615e19b5c75f787"
    }
  ],
  "repository": {
    "id": 20580498,
    "name": "kubernetes",
    "owner": {
	"name": "kubernetes",
	"login": "kubernetes"
    },
    "url": "https://github.com/kubernetes/kubernetes"
  },
  "pusher": {
    "name": "k8s-merge-robot",
    "email": "<EMAIL>"
  }
}`

	var pushEv github.PushEvent
	if err := json.Unmarshal([]byte(pushStr), &pushEv); err != nil {
		t.Fatalf("Failed to parse Push Notification: %s", err)
	}

	// Non bot user merged the PR
	pushEvManual := pushEv
	pushEvManual.Pusher.Name = "<NAME>"
	pushEvManual.Pusher.Email = "<EMAIL>"
	pushEvManual.Sender.Login = "tester"
	pushEvManual.Ref = "refs/heads/master"

	pushEvManualBranchExempted := pushEv
	pushEvManualBranchExempted.Pusher.Name = "<NAME>"
	pushEvManualBranchExempted.Pusher.Email = "<EMAIL>"
	pushEvManualBranchExempted.Sender.Login = "WTeened"
	pushEvManualBranchExempted.Ref = "refs/heads/warrens-branch"

	pushEvManualNotBranchExempted := pushEvManualBranchExempted
	pushEvManualNotBranchExempted.Ref = "refs/heads/master"

	pushEvManualCreated := pushEvManual
	pushEvManualCreated.Created = true
	pushEvManualCreated.Ref = "refs/heads/release-1.99"
	pushEvManualCreated.Compare = "https://github.com/kubernetes/kubernetes/compare/045a6dca0784"

	pushEvManualDeleted := pushEvManual
	pushEvManualDeleted.Deleted = true
	pushEvManualDeleted.Ref = "refs/heads/release-1.99"
	pushEvManualDeleted.Compare = "https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...000000000000"

	pushEvManualForced := pushEvManual
	pushEvManualForced.Forced = true

	noMessages := map[string][]string{}
	stdWarningMessages := map[string][]string{
		"sig-contribex":  {"*Warning:* tester (<@tester>) manually merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"},
		"kubernetes-dev": {"*Warning:* tester (<@tester>) manually merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"}}

	createdWarningMessages := map[string][]string{
		"sig-contribex":  {"*Warning:* tester (<@tester>) pushed a new branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/045a6dca0784"},
		"kubernetes-dev": {"*Warning:* tester (<@tester>) pushed a new branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/045a6dca0784"}}

	deletedWarningMessages := map[string][]string{
		"sig-contribex":  {"*Warning:* tester (<@tester>) deleted a branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...000000000000"},
		"kubernetes-dev": {"*Warning:* tester (<@tester>) deleted a branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...000000000000"}}

	forcedWarningMessages := map[string][]string{
		"sig-contribex":  {"*Warning:* tester (<@tester>) *force* merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"},
		"kubernetes-dev": {"*Warning:* tester (<@tester>) *force* merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"}}

	type testCase struct {
		name             string
		pushReq          github.PushEvent
		expectedMessages map[string][]string
	}

	testcases := []testCase{
		{
			name:             "If PR merged manually by a user, we send message to sig-contribex and kubernetes-dev.",
			pushReq:          pushEvManual,
			expectedMessages: stdWarningMessages,
		},
		{
			name:             "If PR force merged by a user, we send message to sig-contribex and kubernetes-dev with force merge message.",
			pushReq:          pushEvManualForced,
			expectedMessages: forcedWarningMessages,
		},
		{
			name:             "If PR merged by k8s merge bot we should NOT send message to sig-contribex and kubernetes-dev.",
			pushReq:          pushEv,
			expectedMessages: noMessages,
		},
		{
			name:             "If PR merged by a user not in the exemption list but in THIS branch exemption list, we should NOT send a message to sig-contribex and kubernetes-dev.",
			pushReq:          pushEvManualBranchExempted,
			expectedMessages: noMessages,
		},
		{
			name:             "If PR merged by a user not in the exemption list, in a branch exemption list, but not THIS branch exemption list, we should send a message to sig-contribex and kubernetes-dev.",
			pushReq:          pushEvManualBranchExempted,
			expectedMessages: noMessages,
		},
		{
			name:             "If a branch is created by a non-exempted user, we send message to sig-contribex and kubernetes-dev with branch created message.",
			pushReq:          pushEvManualCreated,
			expectedMessages: createdWarningMessages,
		},
		{
			name:             "If a branch is deleted by a non-exempted user, we send message to sig-contribex and kubernetes-dev with branch deleted message.",
			pushReq:          pushEvManualDeleted,
			expectedMessages: deletedWarningMessages,
		},
	}

	pc := client{
		SlackConfig: plugins.Slack{
			MergeWarnings: []plugins.MergeWarning{
				{
					Repos:       []string{"kubernetes/kubernetes"},
					Channels:    []string{"kubernetes-dev", "sig-contribex"},
					ExemptUsers: []string{"k8s-merge-robot"},
					ExemptBranches: map[string][]string{<commit_msg>prow: rename kubernetes-dev in testdata<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package slackevents

import (
	"encoding/json"
	"strings"
	"testing"

	"k8s.io/test-infra/prow/config"
	"k8s.io/test-infra/prow/github"
	"k8s.io/test-infra/prow/github/fakegithub"
	"k8s.io/test-infra/prow/plugins"
	"k8s.io/test-infra/prow/slack"
)

type FakeClient struct {
	SentMessages map[string][]string
}

func (fk *FakeClient) WriteMessage(text string, channel string) error {
	fk.SentMessages[channel] = append(fk.SentMessages[channel], text)
	return nil
}

func TestPush(t *testing.T) {
	var pushStr = `{
  "ref": "refs/heads/master",
  "before": "d73a75b4b1ddb63870954b9a60a63acaa4cb1ca5",
  "after": "045a6dca07840efaf3311450b615e19b5c75f787",
  "created": false,
  "deleted": false,
  "forced": false,
  "compare": "https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784",
  "commits": [
    {
      "id": "8427d5a27478c80167fd66affe1bd7cd01d3f9a8",
      "message": "Decrease fluentd cpu request",
      "url": "https://github.com/kubernetes/kubernetes/commit/8427d5<PASSWORD>78c<PASSWORD>7fd66affe1bd7cd01d3f9a8"
    },
    {
      "id": "045a6dca07840efaf3311450b615e19b5c75f787",
      "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",
      "url": "https://github.com/kubernetes/kubernetes/commit/045a6dca07840efaf3311450b615e19b5c75f787"
    }
  ],
  "repository": {
    "id": 20580498,
    "name": "kubernetes",
    "owner": {
	"name": "kubernetes",
	"login": "kubernetes"
    },
    "url": "https://github.com/kubernetes/kubernetes"
  },
  "pusher": {
    "name": "k8s-merge-robot",
    "email": "<EMAIL>"
  }
}`

	var pushEv github.PushEvent
	if err := json.Unmarshal([]byte(pushStr), &pushEv); err != nil {
		t.Fatalf("Failed to parse Push Notification: %s", err)
	}

	// Non bot user merged the PR
	pushEvManual := pushEv
	pushEvManual.Pusher.Name = "<NAME>"
	pushEvManual.Pusher.Email = "<EMAIL>"
	pushEvManual.Sender.Login = "tester"
	pushEvManual.Ref = "refs/heads/master"

	pushEvManualBranchExempted := pushEv
	pushEvManualBranchExempted.Pusher.Name = "<NAME>"
	pushEvManualBranchExempted.Pusher.Email = "<EMAIL>"
	pushEvManualBranchExempted.Sender.Login = "WTeened"
	pushEvManualBranchExempted.Ref = "refs/heads/warrens-branch"

	pushEvManualNotBranchExempted := pushEvManualBranchExempted
	pushEvManualNotBranchExempted.Ref = "refs/heads/master"

	pushEvManualCreated := pushEvManual
	pushEvManualCreated.Created = true
	pushEvManualCreated.Ref = "refs/heads/release-1.99"
	pushEvManualCreated.Compare = "https://github.com/kubernetes/kubernetes/compare/045a6dca0784"

	pushEvManualDeleted := pushEvManual
	pushEvManualDeleted.Deleted = true
	pushEvManualDeleted.Ref = "refs/heads/release-1.99"
	pushEvManualDeleted.Compare = "https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...000000000000"

	pushEvManualForced := pushEvManual
	pushEvManualForced.Forced = true

	noMessages := map[string][]string{}
	stdWarningMessages := map[string][]string{
		"sig-contribex":  {"*Warning:* tester (<@tester>) manually merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"},
		"kubernetes-foo": {"*Warning:* tester (<@tester>) manually merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"}}

	createdWarningMessages := map[string][]string{
		"sig-contribex":  {"*Warning:* tester (<@tester>) pushed a new branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/045a6dca0784"},
		"kubernetes-foo": {"*Warning:* tester (<@tester>) pushed a new branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/045a6dca0784"}}

	deletedWarningMessages := map[string][]string{
		"sig-contribex":  {"*Warning:* tester (<@tester>) deleted a branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...000000000000"},
		"kubernetes-foo": {"*Warning:* tester (<@tester>) deleted a branch (release-1.99): https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...000000000000"}}

	forcedWarningMessages := map[string][]string{
		"sig-contribex":  {"*Warning:* tester (<@tester>) *force* merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"},
		"kubernetes-foo": {"*Warning:* tester (<@tester>) *force* merged 2 commit(s) into master: https://github.com/kubernetes/kubernetes/compare/d73a75b4b1dd...045a6dca0784"}}

	type testCase struct {
		name             string
		pushReq          github.PushEvent
		expectedMessages map[string][]string
	}

	testcases := []testCase{
		{
			name:             "If PR merged manually by a user, we send message to sig-contribex and kubernetes-foo.",
			pushReq:          pushEvManual,
			expectedMessages: stdWarningMessages,
		},
		{
			name:             "If PR force merged by a user, we send message to sig-contribex and kubernetes-foo with force merge message.",
			pushReq:          pushEvManualForced,
			expectedMessages: forcedWarningMessages,
		},
		{
			name:             "If PR merged by k8s merge bot we should NOT send message to sig-contribex and kubernetes-foo.",
			pushReq:          pushEv,
			expectedMessages: noMessages,
		},
		{
			name:             "If PR merged by a user not in the exemption list but in THIS branch exemption list, we should NOT send a message to sig-contribex and kubernetes-foo.",
			pushReq:          pushEvManualBranchExempted,
			expectedMessages: noMessages,
		},
		{
			name:             "If PR merged by a user not in the exemption list, in a branch exemption list, but not THIS branch exemption list, we should send a message to sig-contribex and kubernetes-foo.",
			pushReq:          pushEvManualBranchExempted,
			expectedMessages: noMessages,
		},
		{
			name:             "If a branch is created by a non-exempted user, we send message to sig-contribex and kubernetes-foo with branch created message.",
			pushReq:          pushEvManualCreated,
			expectedMessages: createdWarningMessages,
		},
		{
			name:             "If a branch is deleted by a non-exempted user, we send message to sig-contribex and kubernetes-foo with branch deleted message.",
			pushReq:          pushEvManualDeleted,
			expectedMessages: deletedWarningMessages,
		},
	}

	pc := client{
		SlackConfig: plugins.Slack{
			MergeWarnings: []plugins.MergeWarning{
				{
					Repos:       []string{"kubernetes/kubernetes"},
					Channels:    []string{"kubernetes-foo", "sig-contribex"},
					ExemptUsers: []string{"k8s-merge-robot"},
					ExemptBranches: map[string][]string{
{'fraction_non_alphanumeric': 0.12610741971207087, 'fraction_numerical': 0.049210963455149505, 'mean_word_length': 4.14565527065527, 'pattern_counts': {'":': 64, '<': 31, '<?xml version=': 0, '>': 31, 'https://': 28, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 6, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1074888', 'n_tokens_mistral': 5508, 'n_tokens_neox': 4833, 'n_words': 1095}