github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/experiment/add-hook/main_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 main
    18  
    19  import (
    20  	"errors"
    21  	"flag"
    22  	"fmt"
    23  	"reflect"
    24  	"testing"
    25  
    26  	"k8s.io/test-infra/prow/flagutil"
    27  	"k8s.io/test-infra/prow/github"
    28  )
    29  
    30  func TestGetOptions(t *testing.T) {
    31  	defArgs := map[string][]string{
    32  		"--hmac-path":         {"/fake/hmac-file"},
    33  		"--hook-url":          {"https://not-a-url"},
    34  		"--repo":              {"fake-org/fake-repo"},
    35  		"--github-token-path": {"/fake/github-token"},
    36  	}
    37  	cases := []struct {
    38  		name     string
    39  		args     map[string][]string
    40  		expected func(*options)
    41  		err      bool
    42  	}{
    43  		{
    44  			name: "reject empty --hmac-path",
    45  			args: map[string][]string{
    46  				"--hmac-path": nil,
    47  			},
    48  			err: true,
    49  		},
    50  		{
    51  			name: "reject empty --hook-url",
    52  			args: map[string][]string{
    53  				"--hook-url": nil,
    54  			},
    55  			err: true,
    56  		},
    57  		{
    58  			name: "empty --repo",
    59  			args: map[string][]string{
    60  				"--repo": nil,
    61  			},
    62  			err: true,
    63  		},
    64  		{
    65  			name: "multi repo",
    66  			args: map[string][]string{
    67  				"--repo": {"org1", "org2/repo"},
    68  			},
    69  			expected: func(o *options) {
    70  				o.repo = flagutil.NewStrings()
    71  				o.repo.Set("org1")
    72  				o.repo.Set("org2/repo")
    73  			},
    74  		},
    75  		{
    76  			name: "full flags",
    77  			args: map[string][]string{
    78  				"--event":   {"this", "that"},
    79  				"--confirm": {"true"},
    80  			},
    81  			expected: func(o *options) {
    82  				o.events.Set("this")
    83  				o.events.Set("that")
    84  				o.confirm = true
    85  			},
    86  		},
    87  	}
    88  
    89  	for _, tc := range cases {
    90  		t.Run(tc.name, func(t *testing.T) {
    91  			var args []string
    92  			for k, v := range defArgs {
    93  				if _, ok := tc.args[k]; !ok {
    94  					tc.args[k] = v
    95  				}
    96  			}
    97  
    98  			for k, v := range tc.args {
    99  				for _, arg := range v {
   100  					args = append(args, k+"="+arg)
   101  				}
   102  			}
   103  
   104  			expected := options{
   105  				hmacPath: "/fake/hmac-file",
   106  				hookURL:  "https://not-a-url",
   107  				events:   flagutil.NewStrings(github.AllHookEvents...),
   108  			}
   109  			expected.repo.Set("fake-org/fake-repo")
   110  
   111  			if tc.expected != nil {
   112  				tc.expected(&expected)
   113  			}
   114  
   115  			o, err := getOptions(flag.NewFlagSet("fake-flags", flag.ExitOnError), args)
   116  			if o != nil { // TODO(fejta): github.GitHubOptions not unit testable
   117  				expected.GitHubOptions = o.GitHubOptions
   118  			}
   119  			switch {
   120  			case err != nil:
   121  				if !tc.err {
   122  					t.Errorf("unexpected error %s: %v", args, err)
   123  				}
   124  			case tc.err:
   125  				t.Error("failed to receive an error")
   126  			case !reflect.DeepEqual(*o, expected):
   127  				t.Errorf("%#v != actual %#v", expected, o)
   128  			}
   129  		})
   130  	}
   131  }
   132  
   133  func TestFindHook(t *testing.T) {
   134  	const goal = "http://random-url"
   135  	number := 7
   136  	cases := []struct {
   137  		name     string
   138  		hooks    []github.Hook
   139  		expected *int
   140  	}{
   141  		{
   142  			name:  "nil on no match",
   143  			hooks: []github.Hook{{}, {}},
   144  		},
   145  		{
   146  			name: "return matched id",
   147  			hooks: []github.Hook{{
   148  				ID: number,
   149  				Config: github.HookConfig{
   150  					URL: goal,
   151  				},
   152  			}},
   153  			expected: &number,
   154  		},
   155  	}
   156  
   157  	for _, tc := range cases {
   158  		actual := findHook(tc.hooks, goal)
   159  		if !reflect.DeepEqual(actual, tc.expected) {
   160  			t.Errorf("%s: expected %v != actual %v", tc.name, tc.expected, actual)
   161  		}
   162  	}
   163  }
   164  
   165  func TestReconcileHook(t *testing.T) {
   166  	const goal = "http://goal-url"
   167  	const targetId = 1000
   168  	secret := "ingredient"
   169  	j := "json"
   170  	cases := []struct {
   171  		name         string
   172  		org          string
   173  		hooks        []github.Hook
   174  		expectCreate bool
   175  		expectEdit   bool
   176  		err          bool
   177  	}{
   178  		{
   179  			name: "fail on list error",
   180  			org:  "list-error",
   181  			err:  true,
   182  		},
   183  		{
   184  			name: "fail on create error",
   185  			org:  "create-error",
   186  			err:  true,
   187  		},
   188  		{
   189  			name: "fail on edit error",
   190  			org:  "edit-error",
   191  			hooks: []github.Hook{
   192  				{
   193  					Config: github.HookConfig{
   194  						URL: goal,
   195  					},
   196  				},
   197  			},
   198  			err: true,
   199  		},
   200  		{
   201  			name:         "create when empty",
   202  			expectCreate: true,
   203  		},
   204  		{
   205  			name: "create when no match",
   206  			hooks: []github.Hook{
   207  				{
   208  					ID: targetId + 6666,
   209  					Config: github.HookConfig{
   210  						URL: "http://random-url",
   211  					},
   212  				},
   213  			},
   214  			expectCreate: true,
   215  		},
   216  		{
   217  			name: "edit exiting item",
   218  			hooks: []github.Hook{
   219  				{
   220  					ID: targetId,
   221  					Config: github.HookConfig{
   222  						URL: goal,
   223  					},
   224  				},
   225  			},
   226  			expectEdit: true,
   227  		},
   228  	}
   229  
   230  	for _, tc := range cases {
   231  		var created, edited *github.HookRequest
   232  		ch := changer{
   233  			lister: func(org string) ([]github.Hook, error) {
   234  				if org == "list-error" {
   235  					return nil, errors.New("inject list error")
   236  				}
   237  				return tc.hooks, nil
   238  			},
   239  			editor: func(org string, id int, req github.HookRequest) error {
   240  				if org == "edit-error" {
   241  					return errors.New("inject edit error")
   242  				}
   243  				if id != targetId {
   244  					return fmt.Errorf("id %d != expected %d", id, targetId)
   245  				}
   246  				edited = &req
   247  				return nil
   248  			},
   249  			creator: func(org string, req github.HookRequest) (int, error) {
   250  				if org == "create-error" {
   251  					return 0, errors.New("inject create error")
   252  				}
   253  				if created != nil {
   254  					return 0, errors.New("already created")
   255  				}
   256  				created = &req
   257  				return targetId, nil
   258  			},
   259  		}
   260  		req := github.HookRequest{
   261  			Name:   "web",
   262  			Events: []string{"random"},
   263  			Config: &github.HookConfig{
   264  				URL:         goal,
   265  				ContentType: &j,
   266  				Secret:      &secret,
   267  			},
   268  		}
   269  
   270  		err := reconcileHook(ch, tc.org, req)
   271  		switch {
   272  		case err != nil:
   273  			if !tc.err {
   274  				t.Errorf("unexpected error: %v", err)
   275  			}
   276  		case tc.err:
   277  			t.Error("failed to receive an error")
   278  		case tc.expectCreate && created == nil:
   279  			t.Error("failed to create")
   280  		case tc.expectEdit && edited == nil:
   281  			t.Error("failed to edit")
   282  		case created != nil && !reflect.DeepEqual(req, *created):
   283  			t.Errorf("created %#v != expected %#v", *created, req)
   284  		case edited != nil && !reflect.DeepEqual(req, *edited):
   285  			t.Errorf("edited %#v != expected %#v", *edited, req)
   286  		}
   287  	}
   288  }