github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/report/report_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 report
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  	"testing"
    23  
    24  	"k8s.io/test-infra/prow/github"
    25  	"k8s.io/test-infra/prow/kube"
    26  )
    27  
    28  func TestParseIssueComment(t *testing.T) {
    29  	var testcases = []struct {
    30  		name             string
    31  		context          string
    32  		state            string
    33  		ics              []github.IssueComment
    34  		expectedDeletes  []int
    35  		expectedContexts []string
    36  		expectedUpdate   int
    37  	}{
    38  		{
    39  			name:    "should delete old style comments",
    40  			context: "Jenkins foo test",
    41  			state:   github.StatusSuccess,
    42  			ics: []github.IssueComment{
    43  				{
    44  					User: github.User{Login: "k8s-ci-robot"},
    45  					Body: "Jenkins foo test **failed** for such-and-such.",
    46  					ID:   12345,
    47  				},
    48  				{
    49  					User: github.User{Login: "someone-else"},
    50  					Body: "Jenkins foo test **failed**!? Why?",
    51  					ID:   12356,
    52  				},
    53  				{
    54  					User: github.User{Login: "k8s-ci-robot"},
    55  					Body: "Jenkins foo test **failed** for so-and-so.",
    56  					ID:   12367,
    57  				},
    58  				{
    59  					User: github.User{Login: "k8s-ci-robot"},
    60  					Body: "Jenkins bar test **failed** for something-or-other.",
    61  					ID:   12378,
    62  				},
    63  			},
    64  			expectedDeletes: []int{12345, 12367},
    65  		},
    66  		{
    67  			name:             "should create a new comment",
    68  			context:          "bla test",
    69  			state:            github.StatusFailure,
    70  			expectedContexts: []string{"bla test"},
    71  		},
    72  		{
    73  			name:    "should not delete an up-to-date comment",
    74  			context: "bla test",
    75  			state:   github.StatusSuccess,
    76  			ics: []github.IssueComment{
    77  				{
    78  					User: github.User{Login: "k8s-ci-robot"},
    79  					Body: "--- | --- | ---\nfoo test | something | or other\n\n",
    80  				},
    81  			},
    82  		},
    83  		{
    84  			name:    "should delete when all tests pass",
    85  			context: "bla test",
    86  			state:   github.StatusSuccess,
    87  			ics: []github.IssueComment{
    88  				{
    89  					User: github.User{Login: "k8s-ci-robot"},
    90  					Body: "--- | --- | ---\nbla test | something | or other\n\n" + commentTag,
    91  					ID:   123,
    92  				},
    93  			},
    94  			expectedDeletes:  []int{123},
    95  			expectedContexts: []string{},
    96  		},
    97  		{
    98  			name:    "should delete a passing test with \\r",
    99  			context: "bla test",
   100  			state:   github.StatusSuccess,
   101  			ics: []github.IssueComment{
   102  				{
   103  					User: github.User{Login: "k8s-ci-robot"},
   104  					Body: "--- | --- | ---\r\nbla test | something | or other\r\n\r\n" + commentTag,
   105  					ID:   123,
   106  				},
   107  			},
   108  			expectedDeletes:  []int{123},
   109  			expectedContexts: []string{},
   110  		},
   111  
   112  		{
   113  			name:    "should update a failed test",
   114  			context: "bla test",
   115  			state:   github.StatusFailure,
   116  			ics: []github.IssueComment{
   117  				{
   118  					User: github.User{Login: "k8s-ci-robot"},
   119  					Body: "--- | --- | ---\nbla test | something | or other\n\n" + commentTag,
   120  					ID:   123,
   121  				},
   122  			},
   123  			expectedDeletes:  []int{123},
   124  			expectedContexts: []string{"bla test"},
   125  		},
   126  		{
   127  			name:    "should preserve old results when updating",
   128  			context: "bla test",
   129  			state:   github.StatusFailure,
   130  			ics: []github.IssueComment{
   131  				{
   132  					User: github.User{Login: "k8s-ci-robot"},
   133  					Body: "--- | --- | ---\nbla test | something | or other\nfoo test | wow | aye\n\n" + commentTag,
   134  					ID:   123,
   135  				},
   136  			},
   137  			expectedDeletes:  []int{123},
   138  			expectedContexts: []string{"bla test", "foo test"},
   139  		},
   140  		{
   141  			name:    "should merge duplicates",
   142  			context: "bla test",
   143  			state:   github.StatusFailure,
   144  			ics: []github.IssueComment{
   145  				{
   146  					User: github.User{Login: "k8s-ci-robot"},
   147  					Body: "--- | --- | ---\nbla test | something | or other\nfoo test | wow such\n\n" + commentTag,
   148  					ID:   123,
   149  				},
   150  				{
   151  					User: github.User{Login: "k8s-ci-robot"},
   152  					Body: "--- | --- | ---\nfoo test | beep | boop\n\n" + commentTag,
   153  					ID:   124,
   154  				},
   155  			},
   156  			expectedDeletes:  []int{123, 124},
   157  			expectedContexts: []string{"bla test", "foo test"},
   158  		},
   159  		{
   160  			name:    "should update an old comment when a test passes",
   161  			context: "bla test",
   162  			state:   github.StatusSuccess,
   163  			ics: []github.IssueComment{
   164  				{
   165  					User: github.User{Login: "k8s-ci-robot"},
   166  					Body: "--- | --- | ---\nbla test | something | or other\nfoo test | wow | aye\n\n" + commentTag,
   167  					ID:   123,
   168  				},
   169  			},
   170  			expectedDeletes:  []int{},
   171  			expectedContexts: []string{"foo test"},
   172  			expectedUpdate:   123,
   173  		},
   174  	}
   175  	for _, tc := range testcases {
   176  		pj := kube.ProwJob{
   177  			Spec: kube.ProwJobSpec{
   178  				Context: tc.context,
   179  				Refs:    kube.Refs{Pulls: []kube.Pull{{}}},
   180  			},
   181  			Status: kube.ProwJobStatus{
   182  				State: kube.ProwJobState(tc.state),
   183  			},
   184  		}
   185  		deletes, entries, update := parseIssueComments(pj, "k8s-ci-robot", tc.ics)
   186  		if len(deletes) != len(tc.expectedDeletes) {
   187  			t.Errorf("It %s: wrong number of deletes. Got %v, expected %v", tc.name, deletes, tc.expectedDeletes)
   188  		} else {
   189  			for _, edel := range tc.expectedDeletes {
   190  				found := false
   191  				for _, del := range deletes {
   192  					if del == edel {
   193  						found = true
   194  						break
   195  					}
   196  				}
   197  				if !found {
   198  					t.Errorf("It %s: expected to find %d in %v", tc.name, edel, deletes)
   199  				}
   200  			}
   201  		}
   202  		if len(entries) != len(tc.expectedContexts) {
   203  			t.Errorf("It %s: wrong number of entries. Got %v, expected %v", tc.name, entries, tc.expectedContexts)
   204  		} else {
   205  			for _, econt := range tc.expectedContexts {
   206  				found := false
   207  				for _, ent := range entries {
   208  					if strings.Contains(ent, econt) {
   209  						found = true
   210  						break
   211  					}
   212  				}
   213  				if !found {
   214  					t.Errorf("It %s: expected to find %s in %v", tc.name, econt, entries)
   215  				}
   216  			}
   217  		}
   218  		if tc.expectedUpdate != update {
   219  			t.Errorf("It %s: expected update %d, got %d", tc.name, tc.expectedUpdate, update)
   220  		}
   221  	}
   222  }
   223  
   224  type fakeGhClient struct {
   225  	status []github.Status
   226  }
   227  
   228  func (gh fakeGhClient) BotName() (string, error) {
   229  	return "BotName", nil
   230  }
   231  func (gh *fakeGhClient) CreateStatus(org, repo, ref string, s github.Status) error {
   232  	gh.status = append(gh.status, s)
   233  	return nil
   234  
   235  }
   236  func (gh fakeGhClient) ListIssueComments(org, repo string, number int) ([]github.IssueComment, error) {
   237  	return nil, nil
   238  }
   239  func (gh fakeGhClient) CreateComment(org, repo string, number int, comment string) error {
   240  	return nil
   241  }
   242  func (gh fakeGhClient) DeleteComment(org, repo string, ID int) error {
   243  	return nil
   244  }
   245  func (gh fakeGhClient) EditComment(org, repo string, ID int, comment string) error {
   246  	return nil
   247  }
   248  
   249  func createChildren(pjs *kube.ProwJobSpec, d int) int {
   250  	count := 0
   251  	for i := 0; i < d; i++ {
   252  		report := false
   253  		if d%2 == 0 {
   254  			report = true
   255  			count++
   256  		}
   257  		npjs := &kube.ProwJobSpec{
   258  			Report:  report,
   259  			Context: fmt.Sprintf("%s/child_%d", pjs.Context, i),
   260  		}
   261  		count += createChildren(npjs, d-1)
   262  		pjs.RunAfterSuccess = append(pjs.RunAfterSuccess, *npjs)
   263  	}
   264  	return count
   265  }
   266  
   267  func TestReportStatus(t *testing.T) {
   268  	type tc struct {
   269  		name        string
   270  		pj          kube.ProwJob
   271  		statusCount int
   272  	}
   273  	children := 3
   274  	createTc := func(n string, state kube.ProwJobState, report bool) tc {
   275  
   276  		pj := kube.ProwJob{
   277  			Status: kube.ProwJobStatus{
   278  				State:       state,
   279  				Description: "message",
   280  				URL:         "http://mytest.com",
   281  			},
   282  			Spec: kube.ProwJobSpec{
   283  				Context: "parent",
   284  				Report:  report,
   285  				Refs: kube.Refs{
   286  					Org:  "k8s",
   287  					Repo: "test-infra",
   288  					Pulls: []kube.Pull{{
   289  						Author: "me",
   290  						Number: 1,
   291  						SHA:    "abcdef",
   292  					}},
   293  				},
   294  			},
   295  		}
   296  
   297  		statusCount := createChildren(&pj.Spec, children)
   298  		if report {
   299  			statusCount++
   300  		}
   301  
   302  		return tc{
   303  			name:        n,
   304  			pj:          pj,
   305  			statusCount: statusCount,
   306  		}
   307  	}
   308  	for _, tc := range []tc{
   309  		createTc("successful job", kube.SuccessState, true),
   310  		createTc("successful job", kube.SuccessState, false),
   311  		createTc("pending jobs", kube.PendingState, true),
   312  		createTc("pending jobs", kube.PendingState, false),
   313  	} {
   314  		ghc := &fakeGhClient{}
   315  		if err := reportStatus(ghc, tc.pj, parentJobChanged); err != nil {
   316  			t.Error(err)
   317  		}
   318  		if tc.pj.Status.State == kube.SuccessState {
   319  			if tc.pj.Spec.Report {
   320  				if len(ghc.status) != 1 {
   321  					t.Errorf("There should only be one status sent, found %d", len(ghc.status))
   322  				}
   323  			} else {
   324  				if len(ghc.status) != 0 {
   325  					t.Errorf("There should only no status sent, found %d", len(ghc.status))
   326  				}
   327  			}
   328  		} else {
   329  			if len(ghc.status) != tc.statusCount {
   330  				t.Errorf("There should be %d status, found %d", tc.statusCount, len(ghc.status))
   331  			}
   332  			for i := 1; i < tc.statusCount; i++ {
   333  				if !strings.HasPrefix(ghc.status[i].Description, parentJobChanged) {
   334  					t.Errorf("Description should start with prefix %s", parentJobChanged)
   335  				}
   336  			}
   337  		}
   338  	}
   339  }