github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/pkg/plugins/lifecycle/lifecycle_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 lifecycle
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  
    23  	"github.com/sirupsen/logrus"
    24  
    25  	"sigs.k8s.io/prow/pkg/github"
    26  	"sigs.k8s.io/prow/pkg/labels"
    27  )
    28  
    29  type fakeClient struct {
    30  	// current labels
    31  	labels []string
    32  	// labels that are added
    33  	added []string
    34  	// labels that are removed
    35  	removed []string
    36  	// commentsAdded tracks the comments in the client
    37  	commentsAdded map[int][]string
    38  }
    39  
    40  func (c *fakeClient) AddLabel(owner, repo string, number int, label string) error {
    41  	c.added = append(c.added, label)
    42  	c.labels = append(c.labels, label)
    43  	return nil
    44  }
    45  
    46  func (c *fakeClient) RemoveLabel(owner, repo string, number int, label string) error {
    47  	c.removed = append(c.removed, label)
    48  
    49  	// remove from existing labels
    50  	for k, v := range c.labels {
    51  		if label == v {
    52  			c.labels = append(c.labels[:k], c.labels[k+1:]...)
    53  			break
    54  		}
    55  	}
    56  
    57  	return nil
    58  }
    59  
    60  func (c *fakeClient) GetIssueLabels(owner, repo string, number int) ([]github.Label, error) {
    61  	la := []github.Label{}
    62  	for _, l := range c.labels {
    63  		la = append(la, github.Label{Name: l})
    64  	}
    65  	return la, nil
    66  }
    67  
    68  // CreateComment adds and tracks a comment in the client
    69  func (c *fakeClient) CreateComment(owner, repo string, number int, comment string) error {
    70  	c.commentsAdded[number] = append(c.commentsAdded[number], comment)
    71  	return nil
    72  }
    73  
    74  // NumComments counts the number of tracked comments
    75  func (c *fakeClient) NumComments() int {
    76  	n := 0
    77  	for _, comments := range c.commentsAdded {
    78  		n += len(comments)
    79  	}
    80  	return n
    81  }
    82  
    83  func TestAddLifecycleLabels(t *testing.T) {
    84  	var testcases = []struct {
    85  		name          string
    86  		isPR          bool
    87  		body          string
    88  		added         []string
    89  		removed       []string
    90  		labels        []string
    91  		expectComment bool
    92  	}{
    93  		{
    94  			name:    "random command -> no-op",
    95  			body:    "/random-command",
    96  			added:   []string{},
    97  			removed: []string{},
    98  			labels:  []string{},
    99  		},
   100  		{
   101  			name:    "remove lifecycle but don't specify state -> no-op",
   102  			body:    "/remove-lifecycle",
   103  			added:   []string{},
   104  			removed: []string{},
   105  			labels:  []string{},
   106  		},
   107  		{
   108  			name:    "add lifecycle but don't specify state -> no-op",
   109  			body:    "/lifecycle",
   110  			added:   []string{},
   111  			removed: []string{},
   112  			labels:  []string{},
   113  		},
   114  		{
   115  			name:    "add lifecycle random -> no-op",
   116  			body:    "/lifecycle random",
   117  			added:   []string{},
   118  			removed: []string{},
   119  			labels:  []string{},
   120  		},
   121  		{
   122  			name:    "remove lifecycle random -> no-op",
   123  			body:    "/remove-lifecycle random",
   124  			added:   []string{},
   125  			removed: []string{},
   126  			labels:  []string{},
   127  		},
   128  		{
   129  			name:    "add frozen and stale with single command -> no-op",
   130  			body:    "/lifecycle frozen stale",
   131  			added:   []string{},
   132  			removed: []string{},
   133  			labels:  []string{},
   134  		},
   135  		{
   136  			name:    "add frozen and random with single command -> no-op",
   137  			body:    "/lifecycle frozen random",
   138  			added:   []string{},
   139  			removed: []string{},
   140  			labels:  []string{},
   141  		},
   142  		{
   143  			name:    "add frozen, don't have it -> frozen added",
   144  			body:    "/lifecycle frozen",
   145  			added:   []string{labels.LifecycleFrozen},
   146  			removed: []string{},
   147  			labels:  []string{},
   148  		},
   149  		{
   150  			name:    "add stale, don't have it -> stale added",
   151  			body:    "/lifecycle stale",
   152  			added:   []string{labels.LifecycleStale},
   153  			removed: []string{},
   154  			labels:  []string{},
   155  		},
   156  		{
   157  			name:    "add rotten, don't have it -> rotten added",
   158  			body:    "/lifecycle rotten",
   159  			added:   []string{labels.LifecycleRotten},
   160  			removed: []string{},
   161  			labels:  []string{},
   162  		},
   163  		{
   164  			name:    "remove frozen, have it -> frozen removed",
   165  			body:    "/remove-lifecycle frozen",
   166  			added:   []string{},
   167  			removed: []string{labels.LifecycleFrozen},
   168  			labels:  []string{labels.LifecycleFrozen},
   169  		},
   170  		{
   171  			name:    "remove stale, have it -> stale removed",
   172  			body:    "/remove-lifecycle stale",
   173  			added:   []string{},
   174  			removed: []string{labels.LifecycleStale},
   175  			labels:  []string{labels.LifecycleStale},
   176  		},
   177  		{
   178  			name:    "remove rotten, have it -> rotten removed",
   179  			body:    "/remove-lifecycle rotten",
   180  			added:   []string{},
   181  			removed: []string{labels.LifecycleRotten},
   182  			labels:  []string{labels.LifecycleRotten},
   183  		},
   184  		{
   185  			name:    "add frozen but have it -> no-op",
   186  			body:    "/lifecycle frozen",
   187  			added:   []string{},
   188  			removed: []string{},
   189  			labels:  []string{labels.LifecycleFrozen},
   190  		},
   191  		{
   192  			name:    "add stale, have active -> stale added, remove active",
   193  			body:    "/lifecycle stale",
   194  			added:   []string{labels.LifecycleStale},
   195  			removed: []string{labels.LifecycleActive},
   196  			labels:  []string{labels.LifecycleActive},
   197  		},
   198  		{
   199  			name:    "add frozen, have rotten -> frozen added, rotten removed",
   200  			body:    "/lifecycle frozen",
   201  			added:   []string{labels.LifecycleFrozen},
   202  			removed: []string{labels.LifecycleRotten},
   203  			labels:  []string{labels.LifecycleRotten},
   204  		},
   205  		{
   206  			name:    "add rotten, have stale -> rotten added, stale removed",
   207  			body:    "/lifecycle rotten",
   208  			added:   []string{labels.LifecycleRotten},
   209  			removed: []string{labels.LifecycleStale},
   210  			labels:  []string{labels.LifecycleStale},
   211  		},
   212  		{
   213  			name:    "add frozen, have stale and rotten -> frozen added, stale and rotten removed",
   214  			body:    "/lifecycle frozen",
   215  			added:   []string{labels.LifecycleFrozen},
   216  			removed: []string{labels.LifecycleStale, labels.LifecycleRotten},
   217  			labels:  []string{labels.LifecycleStale, labels.LifecycleRotten},
   218  		},
   219  		{
   220  			name:    "remove stale, then remove rotten and then add frozen -> stale and rotten removed, frozen added",
   221  			body:    "/remove-lifecycle stale\n/remove-lifecycle rotten\n/lifecycle frozen",
   222  			added:   []string{labels.LifecycleFrozen},
   223  			removed: []string{labels.LifecycleStale, labels.LifecycleRotten},
   224  			labels:  []string{labels.LifecycleStale, labels.LifecycleRotten},
   225  		},
   226  		{
   227  			name:          "add frozen on PR -> add comment",
   228  			isPR:          true,
   229  			body:          "/lifecycle frozen",
   230  			added:         []string{},
   231  			removed:       []string{},
   232  			labels:        []string{},
   233  			expectComment: true,
   234  		},
   235  		{
   236  			name:    "remove frozen on PR, have it -> frozen removed",
   237  			isPR:    true,
   238  			body:    "/remove-lifecycle frozen",
   239  			added:   []string{},
   240  			removed: []string{labels.LifecycleFrozen},
   241  			labels:  []string{labels.LifecycleFrozen},
   242  		},
   243  		{
   244  			name:    "add stale on PR, don't have it -> stale added",
   245  			isPR:    true,
   246  			body:    "/lifecycle stale",
   247  			added:   []string{labels.LifecycleStale},
   248  			removed: []string{},
   249  			labels:  []string{},
   250  		},
   251  	}
   252  	for _, tc := range testcases {
   253  		fc := &fakeClient{
   254  			labels:        tc.labels,
   255  			added:         []string{},
   256  			removed:       []string{},
   257  			commentsAdded: make(map[int][]string),
   258  		}
   259  		e := &github.GenericCommentEvent{
   260  			Body:   tc.body,
   261  			Action: github.GenericCommentActionCreated,
   262  			IsPR:   tc.isPR,
   263  		}
   264  		err := handle(fc, logrus.WithField("plugin", "fake-lifecyle"), e)
   265  		switch {
   266  		case err != nil:
   267  			t.Errorf("%s: unexpected error: %v", tc.name, err)
   268  		case !reflect.DeepEqual(tc.added, fc.added):
   269  			t.Errorf("%s: added %v != actual %v", tc.name, tc.added, fc.added)
   270  		case !reflect.DeepEqual(tc.removed, fc.removed):
   271  			t.Errorf("%s: removed %v != actual %v", tc.name, tc.removed, fc.removed)
   272  		}
   273  
   274  		// if we expected a comment, verify that a comment was made
   275  		numComments := fc.NumComments()
   276  		if tc.expectComment && numComments != 1 {
   277  			t.Errorf("%s: expected 1 comment but received %d comments", tc.name, numComments)
   278  		}
   279  		if !tc.expectComment && numComments != 0 {
   280  			t.Errorf("%s: expected no comments but received %d comments", tc.name, numComments)
   281  		}
   282  	}
   283  }