github.com/abayer/test-infra@v0.0.5/prow/pluginhelp/hook/hook_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 hook
    18  
    19  import (
    20  	"fmt"
    21  	"net/http"
    22  	"net/http/httptest"
    23  	"reflect"
    24  	"sort"
    25  	"testing"
    26  
    27  	"github.com/sirupsen/logrus"
    28  
    29  	"k8s.io/apimachinery/pkg/util/sets"
    30  	"k8s.io/test-infra/prow/github"
    31  	"k8s.io/test-infra/prow/pluginhelp"
    32  	"k8s.io/test-infra/prow/pluginhelp/externalplugins"
    33  	"k8s.io/test-infra/prow/plugins"
    34  )
    35  
    36  type fakeGithubClient map[string][]string
    37  
    38  func (fghc fakeGithubClient) GetRepos(org string, _ bool) ([]github.Repo, error) {
    39  	var repos []github.Repo
    40  	for _, repo := range fghc[org] {
    41  		repos = append(repos, github.Repo{FullName: fmt.Sprintf("%s/%s", org, repo)})
    42  	}
    43  	return repos, nil
    44  }
    45  
    46  type fakePluginAgent plugins.Configuration
    47  
    48  func (fpa fakePluginAgent) Config() *plugins.Configuration {
    49  	config := plugins.Configuration(fpa)
    50  	return &config
    51  }
    52  
    53  func TestGeneratePluginHelp(t *testing.T) {
    54  	orgToRepos := map[string][]string{"org1": {"repo1", "repo2", "repo3"}, "org2": {"repo1"}}
    55  	fghc := fakeGithubClient(orgToRepos)
    56  
    57  	normalHelp := map[string]pluginhelp.PluginHelp{
    58  		"org-plugin": {Description: "org-plugin", Config: map[string]string{"": "overall config"}},
    59  		"repo-plugin1": {
    60  			Description: "repo-plugin1",
    61  			Config: map[string]string{
    62  				"org1/repo1": "repo1 config",
    63  				"org1/repo2": "repo2 config",
    64  			},
    65  		},
    66  		"repo-plugin2": {Description: "repo-plugin2", Config: map[string]string{}},
    67  		"repo-plugin3": {Description: "repo-plugin3", Config: map[string]string{}},
    68  	}
    69  	helpfulExternalHelp := pluginhelp.PluginHelp{Description: "helpful-external"}
    70  	noHelpSever := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    71  		http.Error(w, "404 Not Found", http.StatusNotFound)
    72  	}))
    73  	defer noHelpSever.Close()
    74  	mux := http.NewServeMux()
    75  	externalplugins.ServeExternalPluginHelp(
    76  		mux,
    77  		logrus.WithField("plugin", "helpful-external"),
    78  		func(enabledRepos []string) (*pluginhelp.PluginHelp, error) {
    79  			if got, expected := enabledRepos, []string{"org1/repo1"}; !reflect.DeepEqual(got, expected) {
    80  				t.Errorf("Plugin 'helpful-external' expected to be enabled on repos %q, but got %q.", expected, got)
    81  			}
    82  			return &helpfulExternalHelp, nil
    83  		},
    84  	)
    85  	helpfulServer := httptest.NewServer(mux)
    86  	defer helpfulServer.Close()
    87  
    88  	config := &plugins.Configuration{
    89  		Plugins: map[string][]string{
    90  			"org1":       {"org-plugin"},
    91  			"org1/repo1": {"repo-plugin1", "no-help-plugin"},
    92  			"org1/repo2": {"repo-plugin1", "repo-plugin2"},
    93  			"org2/repo1": {"repo-plugin3"},
    94  		},
    95  		ExternalPlugins: map[string][]plugins.ExternalPlugin{
    96  			"org1/repo1": {
    97  				{Name: "no-endpoint-external", Endpoint: "http://no-endpoint-external", Events: []string{"issue_comment"}},
    98  				{Name: "no-help-external", Endpoint: noHelpSever.URL, Events: []string{"issue_comment"}},
    99  				{Name: "helpful-external", Endpoint: helpfulServer.URL, Events: []string{"pull_request", "issue"}},
   100  			},
   101  		},
   102  	}
   103  	fpa := fakePluginAgent(*config)
   104  
   105  	expectedAllRepos := []string{"org1/repo1", "org1/repo2", "org1/repo3", "org2/repo1"}
   106  
   107  	normalExpectedReposForPlugin := map[string][]string{
   108  		"org-plugin":     {"org1/repo1", "org1/repo2", "org1/repo3"},
   109  		"repo-plugin1":   {"org1/repo1", "org1/repo2"},
   110  		"repo-plugin2":   {"org1/repo2"},
   111  		"repo-plugin3":   {"org2/repo1"},
   112  		"no-help-plugin": {"org1/repo1"},
   113  	}
   114  	normalExpectedPluginsForRepo := map[string][]string{
   115  		"":           {"org-plugin", "repo-plugin1", "repo-plugin2", "repo-plugin3", "no-help-plugin"},
   116  		"org1":       {"org-plugin"},
   117  		"org1/repo1": {"repo-plugin1", "no-help-plugin"},
   118  		"org1/repo2": {"repo-plugin1", "repo-plugin2"},
   119  		"org2/repo1": {"repo-plugin3"},
   120  	}
   121  	normalExpectedEvents := map[string][]string{
   122  		"org-plugin":     {"issue_comment"},
   123  		"repo-plugin1":   {"issue"},
   124  		"repo-plugin2":   {"pull_request"},
   125  		"repo-plugin3":   {"pull_request_review", "pull_request_review_comment"},
   126  		"no-help-plugin": {"issue_comment"},
   127  	}
   128  
   129  	externalExpectedPluginsForRepo := map[string][]string{
   130  		"":           {"no-endpoint-external", "no-help-external", "helpful-external"},
   131  		"org1/repo1": {"no-endpoint-external", "no-help-external", "helpful-external"},
   132  	}
   133  	externalExpectedEvents := map[string][]string{
   134  		"no-endpoint-external": {"issue_comment"},
   135  		"no-help-external":     {"issue_comment"},
   136  		"helpful-external":     {"pull_request", "issue"},
   137  	}
   138  
   139  	registerNormalPlugins(t, normalExpectedEvents, normalHelp, normalExpectedReposForPlugin)
   140  
   141  	help := NewHelpAgent(fpa, fghc).GeneratePluginHelp()
   142  	if help == nil {
   143  		t.Fatal("HelpAgent returned nil Help struct pointer.")
   144  	}
   145  	if got, expected := sets.NewString(help.AllRepos...), sets.NewString(expectedAllRepos...); !got.Equal(expected) {
   146  		t.Errorf("Expected 'AllRepos' to be %q, but got %q.", expected.List(), got.List())
   147  	}
   148  	checkPluginsForRepo := func(expected, got map[string][]string) {
   149  		for _, plugins := range expected {
   150  			sort.Strings(plugins)
   151  		}
   152  		for _, plugins := range got {
   153  			sort.Strings(plugins)
   154  		}
   155  		if !reflect.DeepEqual(expected, got) {
   156  			t.Errorf("Expected repo->plugin map %v, but got %v.", expected, got)
   157  		}
   158  	}
   159  	checkPluginsForRepo(normalExpectedPluginsForRepo, help.RepoPlugins)
   160  	checkPluginsForRepo(externalExpectedPluginsForRepo, help.RepoExternalPlugins)
   161  
   162  	checkPluginHelp := func(plugin string, expected, got pluginhelp.PluginHelp, eventsForPlugin []string) {
   163  		sort.Strings(eventsForPlugin)
   164  		sort.Strings(got.Events)
   165  		if expected, got := eventsForPlugin, got.Events; !reflect.DeepEqual(expected, got) {
   166  			t.Errorf("Expected plugin '%s' to subscribe to events %q, but got %q.", plugin, expected, got)
   167  		}
   168  		// Events field is correct, everything else should match the input exactly.
   169  		got.Events = nil
   170  		if !reflect.DeepEqual(got, expected) {
   171  			t.Errorf("Expected plugin '%s' to have help: %v, but got %v.", plugin, expected, got)
   172  		}
   173  	}
   174  
   175  	for plugin, expected := range normalHelp {
   176  		checkPluginHelp(plugin, expected, help.PluginHelp[plugin], normalExpectedEvents[plugin])
   177  	}
   178  	checkPluginHelp("helpful-external", helpfulExternalHelp, help.ExternalPluginHelp["helpful-external"], externalExpectedEvents["helpful-external"])
   179  }
   180  
   181  func registerNormalPlugins(t *testing.T, pluginsToEvents map[string][]string, pluginHelp map[string]pluginhelp.PluginHelp, expectedRepos map[string][]string) {
   182  	for plugin, events := range pluginsToEvents {
   183  		plugin := plugin
   184  		helpProvider := func(_ *plugins.Configuration, enabledRepos []string) (*pluginhelp.PluginHelp, error) {
   185  			if got, expected := sets.NewString(enabledRepos...), sets.NewString(expectedRepos[plugin]...); !got.Equal(expected) {
   186  				t.Errorf("Plugin '%s' expected to be enabled on repos %q, but got %q.", plugin, expected.List(), got.List())
   187  			}
   188  			help := pluginHelp[plugin]
   189  			return &help, nil
   190  		}
   191  		for _, event := range events {
   192  			switch event {
   193  			case "issue_comment":
   194  				plugins.RegisterIssueCommentHandler(plugin, nil, helpProvider)
   195  			case "issue":
   196  				plugins.RegisterIssueHandler(plugin, nil, helpProvider)
   197  			case "pull_request":
   198  				plugins.RegisterPullRequestHandler(plugin, nil, helpProvider)
   199  			case "pull_request_review":
   200  				plugins.RegisterReviewEventHandler(plugin, nil, helpProvider)
   201  			case "pull_request_review_comment":
   202  				plugins.RegisterReviewCommentEventHandler(plugin, nil, helpProvider)
   203  			default:
   204  				t.Fatalf("Invalid test! Unknown event type '%s' for plugin '%s'.", event, plugin)
   205  			}
   206  		}
   207  	}
   208  }