github.com/yrj2011/jx-test-infra@v0.0.0-20190529031832-7a2065ee98eb/prow/prstatus/prstatus_test.go (about)

     1  /*
     2  Copyright 2018 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 prstatus
    18  
    19  import (
    20  	"context"
    21  	"encoding/gob"
    22  	"golang.org/x/oauth2"
    23  	"io/ioutil"
    24  	"net/http"
    25  	"net/http/httptest"
    26  	"reflect"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/ghodss/yaml"
    31  	gogithub "github.com/google/go-github/github"
    32  	"github.com/gorilla/sessions"
    33  	"github.com/sirupsen/logrus"
    34  
    35  	"k8s.io/test-infra/ghclient"
    36  	"k8s.io/test-infra/prow/config"
    37  	"k8s.io/test-infra/prow/github"
    38  )
    39  
    40  type MockQueryHandler struct {
    41  	prs        []PullRequest
    42  	contextMap map[int][]Context
    43  }
    44  
    45  func (mh *MockQueryHandler) QueryPullRequests(ctx context.Context, ghc githubClient, query string) ([]PullRequest, error) {
    46  	return mh.prs, nil
    47  }
    48  
    49  func (mh *MockQueryHandler) HeadContexts(ghc githubClient, pr PullRequest) ([]Context, error) {
    50  	return mh.contextMap[int(pr.Number)], nil
    51  }
    52  
    53  func (mh *MockQueryHandler) GetUser(*ghclient.Client) (*gogithub.User, error) {
    54  	login := "random_user"
    55  	return &gogithub.User{
    56  		Login: &login,
    57  	}, nil
    58  }
    59  
    60  type fgc struct {
    61  	combinedStatus *github.CombinedStatus
    62  }
    63  
    64  func (c *fgc) Query(context.Context, interface{}, map[string]interface{}) error {
    65  	return nil
    66  }
    67  
    68  func (c *fgc) GetCombinedStatus(org, repo, ref string) (*github.CombinedStatus, error) {
    69  	return c.combinedStatus, nil
    70  }
    71  
    72  func newMockQueryHandler(prs []PullRequest, contextMap map[int][]Context) *MockQueryHandler {
    73  	return &MockQueryHandler{
    74  		prs:        prs,
    75  		contextMap: contextMap,
    76  	}
    77  }
    78  
    79  func createMockAgent(repos []string, config *config.GithubOAuthConfig) *DashboardAgent {
    80  	return &DashboardAgent{
    81  		repos: repos,
    82  		goac:  config,
    83  		log:   logrus.WithField("unit-test", "dashboard-agent"),
    84  	}
    85  }
    86  
    87  func TestHandlePrStatusWithoutLogin(t *testing.T) {
    88  	repos := []string{"mock/repo", "kubernetes/test-infra", "foo/bar"}
    89  	mockCookieStore := sessions.NewCookieStore([]byte("secret-key"))
    90  	mockConfig := &config.GithubOAuthConfig{
    91  		CookieStore: mockCookieStore,
    92  	}
    93  	mockAgent := createMockAgent(repos, mockConfig)
    94  	mockData := UserData{
    95  		Login: false,
    96  	}
    97  
    98  	rr := httptest.NewRecorder()
    99  	request := httptest.NewRequest(http.MethodGet, "/pr-data.js", nil)
   100  
   101  	mockQueryHandler := newMockQueryHandler(nil, nil)
   102  	prHandler := mockAgent.HandlePrStatus(mockQueryHandler)
   103  	prHandler.ServeHTTP(rr, request)
   104  	if rr.Code != http.StatusOK {
   105  		t.Fatalf("Bad status code: %d", rr.Code)
   106  	}
   107  	response := rr.Result()
   108  	defer response.Body.Close()
   109  	body, err := ioutil.ReadAll(response.Body)
   110  	if err != nil {
   111  		t.Fatalf("Error with reading response body: %v", err)
   112  	}
   113  	var dataReturned UserData
   114  	if err := yaml.Unmarshal(body, &dataReturned); err != nil {
   115  		t.Errorf("Error with unmarshaling response: %v", err)
   116  	}
   117  	if !reflect.DeepEqual(dataReturned, mockData) {
   118  		t.Errorf("Invalid user data. Got %v, expected %v", dataReturned, mockData)
   119  	}
   120  }
   121  
   122  func TestHandlePrStatusWithLogin(t *testing.T) {
   123  	repos := []string{"mock/repo", "kubernetes/test-infra", "foo/bar"}
   124  	mockCookieStore := sessions.NewCookieStore([]byte("secret-key"))
   125  	mockConfig := &config.GithubOAuthConfig{
   126  		CookieStore: mockCookieStore,
   127  	}
   128  	mockAgent := createMockAgent(repos, mockConfig)
   129  
   130  	testCases := []struct {
   131  		prs          []PullRequest
   132  		contextMap   map[int][]Context
   133  		expectedData UserData
   134  	}{
   135  		{
   136  			prs:        []PullRequest{},
   137  			contextMap: map[int][]Context{},
   138  			expectedData: UserData{
   139  				Login: true,
   140  			},
   141  		},
   142  		{
   143  			prs: []PullRequest{
   144  				{
   145  					Number: 0,
   146  					Title:  "random pull request",
   147  				},
   148  				{
   149  					Number: 1,
   150  					Title:  "This is a test",
   151  				},
   152  				{
   153  					Number: 2,
   154  					Title:  "test pull request",
   155  				},
   156  			},
   157  			contextMap: map[int][]Context{
   158  				0: {
   159  					{
   160  						Context:     "gofmt-job",
   161  						Description: "job succeed",
   162  						State:       "SUCCESS",
   163  					},
   164  				},
   165  				1: {
   166  					{
   167  						Context:     "verify-bazel-job",
   168  						Description: "job failed",
   169  						State:       "FAILURE",
   170  					},
   171  				},
   172  				2: {
   173  					{
   174  						Context:     "gofmt-job",
   175  						Description: "job succeed",
   176  						State:       "SUCCESS",
   177  					},
   178  					{
   179  						Context:     "verify-bazel-job",
   180  						Description: "job failed",
   181  						State:       "FAILURE",
   182  					},
   183  				},
   184  			},
   185  			expectedData: UserData{
   186  				Login: true,
   187  				PullRequestsWithContexts: []PullRequestWithContext{
   188  					{
   189  						PullRequest: PullRequest{
   190  							Number: 0,
   191  							Title:  "random pull request",
   192  						},
   193  						Contexts: []Context{
   194  							{
   195  								Context:     "gofmt-job",
   196  								Description: "job succeed",
   197  								State:       "SUCCESS",
   198  							},
   199  						},
   200  					},
   201  					{
   202  						PullRequest: PullRequest{
   203  							Number: 1,
   204  							Title:  "This is a test",
   205  						},
   206  						Contexts: []Context{
   207  							{
   208  								Context:     "verify-bazel-job",
   209  								Description: "job failed",
   210  								State:       "FAILURE",
   211  							},
   212  						},
   213  					},
   214  					{
   215  						PullRequest: PullRequest{
   216  							Number: 2,
   217  							Title:  "test pull request",
   218  						},
   219  						Contexts: []Context{
   220  							{
   221  								Context:     "gofmt-job",
   222  								Description: "job succeed",
   223  								State:       "SUCCESS",
   224  							},
   225  							{
   226  								Context:     "verify-bazel-job",
   227  								Description: "job failed",
   228  								State:       "FAILURE",
   229  							},
   230  						},
   231  					},
   232  				},
   233  			},
   234  		},
   235  	}
   236  	for id, testcase := range testCases {
   237  		t.Logf("Test %d:", id)
   238  		rr := httptest.NewRecorder()
   239  		request := httptest.NewRequest(http.MethodGet, "/pr-data.js", nil)
   240  		mockSession, err := sessions.GetRegistry(request).Get(mockCookieStore, tokenSession)
   241  		if err != nil {
   242  			t.Errorf("Error with creating mock session: %v", err)
   243  		}
   244  		gob.Register(oauth2.Token{})
   245  		token := &oauth2.Token{AccessToken: "secret-token", Expiry: time.Now().Add(time.Duration(24*365) * time.Hour)}
   246  		mockSession.Values[tokenKey] = token
   247  		mockSession.Values[loginKey] = "random_user"
   248  		mockQueryHandler := newMockQueryHandler(testcase.prs, testcase.contextMap)
   249  		prHandler := mockAgent.HandlePrStatus(mockQueryHandler)
   250  		prHandler.ServeHTTP(rr, request)
   251  		if rr.Code != http.StatusOK {
   252  			t.Fatalf("Bad status code: %d", rr.Code)
   253  		}
   254  		response := rr.Result()
   255  		body, err := ioutil.ReadAll(response.Body)
   256  		if err != nil {
   257  			t.Fatalf("Error with reading response body: %v", err)
   258  		}
   259  		var dataReturned UserData
   260  		if err := yaml.Unmarshal(body, &dataReturned); err != nil {
   261  			t.Errorf("Error with unmarshaling response: %v", err)
   262  		}
   263  		if !reflect.DeepEqual(dataReturned, testcase.expectedData) {
   264  			t.Fatalf("Invalid user data. Got %v, expected %v.", dataReturned, testcase.expectedData)
   265  		}
   266  		t.Logf("Passed")
   267  		response.Body.Close()
   268  	}
   269  }
   270  
   271  func TestHeadContexts(t *testing.T) {
   272  	repos := []string{"mock/repo", "kubernetes/test-infra", "foo/bar"}
   273  	mockCookieStore := sessions.NewCookieStore([]byte("secret-key"))
   274  	mockConfig := &config.GithubOAuthConfig{
   275  		CookieStore: mockCookieStore,
   276  	}
   277  	mockAgent := createMockAgent(repos, mockConfig)
   278  	testCases := []struct {
   279  		combinedStatus   *github.CombinedStatus
   280  		pr               PullRequest
   281  		expectedContexts []Context
   282  	}{
   283  		{
   284  			combinedStatus:   &github.CombinedStatus{},
   285  			pr:               PullRequest{},
   286  			expectedContexts: []Context{},
   287  		},
   288  		{
   289  			combinedStatus: &github.CombinedStatus{
   290  				Statuses: []github.Status{
   291  					{
   292  						State:       "FAILURE",
   293  						Description: "job failed",
   294  						Context:     "gofmt-job",
   295  					},
   296  					{
   297  						State:       "SUCCESS",
   298  						Description: "job succeed",
   299  						Context:     "k8s-job",
   300  					},
   301  					{
   302  						State:       "PENDING",
   303  						Description: "triggered",
   304  						Context:     "test-job",
   305  					},
   306  				},
   307  			},
   308  			pr: PullRequest{},
   309  			expectedContexts: []Context{
   310  				{
   311  					Context:     "gofmt-job",
   312  					Description: "job failed",
   313  					State:       "FAILURE",
   314  				},
   315  				{
   316  					State:       "SUCCESS",
   317  					Description: "job succeed",
   318  					Context:     "k8s-job",
   319  				},
   320  				{
   321  					State:       "PENDING",
   322  					Description: "triggered",
   323  					Context:     "test-job",
   324  				},
   325  			},
   326  		},
   327  	}
   328  	for id, testcase := range testCases {
   329  		t.Logf("Test %d:", id)
   330  		contexts, err := mockAgent.HeadContexts(&fgc{
   331  			combinedStatus: testcase.combinedStatus,
   332  		}, testcase.pr)
   333  		if err != nil {
   334  			t.Fatalf("Error with getting head contexts")
   335  		}
   336  		if !reflect.DeepEqual(contexts, testcase.expectedContexts) {
   337  			t.Fatalf("Invalid user data. Got %v, expected %v.", contexts, testcase.expectedContexts)
   338  		}
   339  		t.Logf("Passed")
   340  	}
   341  }
   342  
   343  func TestConstructSearchQuery(t *testing.T) {
   344  	repos := []string{"mock/repo", "kubernetes/test-infra", "foo/bar"}
   345  	mockCookieStore := sessions.NewCookieStore([]byte("secret-key"))
   346  	mockConfig := &config.GithubOAuthConfig{
   347  		CookieStore: mockCookieStore,
   348  	}
   349  	mockAgent := createMockAgent(repos, mockConfig)
   350  	query := mockAgent.ConstructSearchQuery("random_username")
   351  	mockQuery := "is:pr state:open author:random_username repo:\"mock/repo\" repo:\"kubernetes/test-infra\" repo:\"foo/bar\""
   352  	if query != mockQuery {
   353  		t.Errorf("Invalid query. Got: %v, expected %v", query, mockQuery)
   354  	}
   355  }