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 }