github.com/abayer/test-infra@v0.0.5/experiment/coverage/apicoverage_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 main 18 19 import ( 20 "bytes" 21 "io" 22 "regexp" 23 "testing" 24 ) 25 26 //NOTE: This method is for avoiding flake tests instead of using reflect.DeepEqual() 27 func equalAPIArray(a, b apiArray) bool { 28 if a == nil && b == nil { 29 return true 30 } 31 if a == nil || b == nil { 32 return false 33 } 34 if len(a) != len(b) { 35 return false 36 } 37 for _, i := range a { 38 found := false 39 for _, j := range b { 40 if i.Method == j.Method && i.URL == j.URL { 41 found = true 42 break 43 } 44 } 45 if !found { 46 return false 47 } 48 } 49 return true 50 } 51 52 func TestParseOpenAPI(t *testing.T) { 53 testCases := []struct { 54 Rawdata []byte 55 Expected apiArray 56 }{ 57 { 58 Rawdata: []byte(`{"paths": {"/resources": { 59 "get": {"description": "get available resources"}}}}`), 60 Expected: apiArray{ 61 {Method: "GET", URL: "/resources"}, 62 }, 63 }, 64 { 65 Rawdata: []byte(`{"paths": {"/resources": { 66 "get": {"description": "get available resources"}, 67 "post": {"description": "create resource"}}}}`), 68 Expected: apiArray{ 69 {Method: "GET", URL: "/resources"}, 70 {Method: "POST", URL: "/resources"}, 71 }, 72 }, 73 { 74 Rawdata: []byte(`{"paths": {"/api/v1/": { 75 "get": {"description": "verify the end of / is removed"}, 76 "post": {"description": "ditto"}}}}`), 77 Expected: apiArray{ 78 {Method: "GET", URL: "/api/v1"}, 79 {Method: "POST", URL: "/api/v1"}, 80 }, 81 }, 82 { 83 Rawdata: []byte(`{"paths": { 84 "/resources": { 85 "get": {"description": "get available resources"}, 86 "post": {"description": "create resource"}}, 87 "/foo": { 88 "get": {"description": "get available foo"}, 89 "post": {"description": "create foo"}, 90 "parameters": [{"type": "string", "description": "This should be ignored", "name": "bar", "in": "query"}]}}}`), 91 Expected: apiArray{ 92 {Method: "GET", URL: "/resources"}, 93 {Method: "POST", URL: "/resources"}, 94 {Method: "GET", URL: "/foo"}, 95 {Method: "POST", URL: "/foo"}, 96 }, 97 }, 98 } 99 for _, test := range testCases { 100 res := parseOpenAPI(test.Rawdata) 101 if !equalAPIArray(res, test.Expected) { 102 t.Errorf("OpenAPI did not match expected for test") 103 t.Errorf("%#v", res) 104 t.Errorf("%#v", test.Expected) 105 } 106 } 107 } 108 109 func TestParseE2eAPILog(t *testing.T) { 110 testCases := []struct { 111 Rawdata io.Reader 112 Expected apiArray 113 }{ 114 { 115 Rawdata: bytes.NewReader( 116 []byte(` 117 I0919 15:34:14.943642 6611 round_trippers.go:414] GET https://k8s-api/api/v1/foo 118 I0919 15:34:16.943642 6611 round_trippers.go:414] POST https://k8s-api/api/v1/bar 119 `)), 120 Expected: apiArray{ 121 {Method: "GET", URL: "/api/v1/foo"}, 122 {Method: "POST", URL: "/api/v1/bar"}, 123 }, 124 }, 125 { 126 Rawdata: bytes.NewReader( 127 []byte(` 128 I0919 15:34:14.943642 6611 round_trippers.go:414] GET https://k8s-api/api/v1/foo?other 129 `)), 130 Expected: apiArray{ 131 {Method: "GET", URL: "/api/v1/foo"}, 132 }, 133 }, 134 } 135 for _, test := range testCases { 136 res := parseE2eAPILog(test.Rawdata) 137 if !equalAPIArray(res, test.Expected) { 138 t.Errorf("APILog did not match expected for test") 139 t.Errorf("Actual: %#v", res) 140 t.Errorf("Expected: %#v", test.Expected) 141 } 142 } 143 } 144 145 func TestParseAPIServerLog(t *testing.T) { 146 testCases := []struct { 147 Rawdata io.Reader 148 Expected apiArray 149 }{ 150 { 151 Rawdata: bytes.NewReader( 152 []byte(` 153 I0413 12:10:56.612005 1 wrap.go:42] GET /api/v1/foo: (1.671974ms) 200 154 I0413 12:10:56.661734 1 wrap.go:42] POST /api/v1/bar: (338.229ニ津郭) 403 155 I0413 12:10:56.672006 1 wrap.go:42] PUT /apis/apiregistration.k8s.io/v1/apiservices/v1.apps/status: (1.671974ms) 200 [[kube-apiserver/v1.11.0 (linux/amd64) kubernetes/7297c1c] 127.0.0.1:44356] 156 `)), 157 Expected: apiArray{ 158 {Method: "GET", URL: "/api/v1/foo"}, 159 {Method: "POST", URL: "/api/v1/bar"}, 160 {Method: "PUT", URL: "/apis/apiregistration.k8s.io/v1/apiservices/v1.apps/status"}, 161 }, 162 }, 163 { 164 Rawdata: bytes.NewReader( 165 []byte(` 166 I0413 12:10:56.612005 1 wrap.go:42] GET /api/v1/foo?other: (1.671974ms) 200 167 `)), 168 Expected: apiArray{ 169 {Method: "GET", URL: "/api/v1/foo"}, 170 }, 171 }, 172 } 173 for _, test := range testCases { 174 res := parseAPIServerLog(test.Rawdata) 175 if !equalAPIArray(res, test.Expected) { 176 t.Errorf("APILog did not match expected for test") 177 t.Errorf("Actual: %#v", res) 178 t.Errorf("Expected: %#v", test.Expected) 179 } 180 } 181 } 182 183 func TestGetTestedAPIs(t *testing.T) { 184 testCases := []struct { 185 apisOpenapi apiArray 186 apisLogs apiArray 187 Expected apiArray 188 }{ 189 { 190 apisOpenapi: apiArray{ 191 {Method: "GET", URL: "/api/v1/foo"}, 192 {Method: "POST", URL: "/api/v1/foo"}, 193 {Method: "GET", URL: "/api/v1/bar"}, 194 {Method: "POST", URL: "/api/v1/bar"}, 195 }, 196 apisLogs: apiArray{ 197 {Method: "GET", URL: "/api/v1/foo"}, 198 {Method: "GET", URL: "/api/v1/bar"}, 199 {Method: "GET", URL: "/api/v1/foo"}, 200 }, 201 Expected: apiArray{ 202 {Method: "GET", URL: "/api/v1/foo"}, 203 {Method: "GET", URL: "/api/v1/bar"}, 204 }, 205 }, 206 } 207 for _, test := range testCases { 208 res := getTestedAPIs(test.apisOpenapi, test.apisLogs) 209 if !equalAPIArray(res, test.Expected) { 210 t.Errorf("APILog did not match expected for test") 211 t.Errorf("Actual: %#v", res) 212 t.Errorf("Expected: %#v", test.Expected) 213 } 214 } 215 } 216 217 func TestGetTestedAPIsByLevel(t *testing.T) { 218 testCases := []struct { 219 Negative bool 220 Reg *regexp.Regexp 221 apisOpenapi apiArray 222 apisTested apiArray 223 ExpectedTested apiArray 224 ExpectedAll apiArray 225 }{ 226 { 227 //Test Alpha APIs are returned 228 Negative: false, 229 Reg: reAlphaAPI, 230 apisOpenapi: apiArray{ 231 {Method: "GET", URL: "/apis/resources/v1/"}, 232 {Method: "POST", URL: "/apis/resources/v1/"}, 233 {Method: "GET", URL: "/apis/resources/v2alpha1/"}, 234 {Method: "POST", URL: "/apis/resources/v2alpha1/"}, 235 {Method: "GET", URL: "/apis/resources/v1beta1/"}, 236 {Method: "POST", URL: "/apis/resources/v1beta1/"}, 237 }, 238 apisTested: apiArray{ 239 {Method: "GET", URL: "/apis/resources/v1/"}, 240 {Method: "GET", URL: "/apis/resources/v2alpha1/"}, 241 {Method: "GET", URL: "/apis/resources/v1beta1/"}, 242 }, 243 ExpectedTested: apiArray{ 244 {Method: "GET", URL: "/apis/resources/v2alpha1/"}, 245 }, 246 ExpectedAll: apiArray{ 247 {Method: "GET", URL: "/apis/resources/v2alpha1/"}, 248 {Method: "POST", URL: "/apis/resources/v2alpha1/"}, 249 }, 250 }, 251 { 252 //Test Beta APIs are returned 253 Negative: false, 254 Reg: reBetaAPI, 255 apisOpenapi: apiArray{ 256 {Method: "GET", URL: "/apis/resources/v1/"}, 257 {Method: "POST", URL: "/apis/resources/v1/"}, 258 {Method: "GET", URL: "/apis/resources/v2alpha1/"}, 259 {Method: "POST", URL: "/apis/resources/v2alpha1/"}, 260 {Method: "GET", URL: "/apis/resources/v1beta1/"}, 261 {Method: "POST", URL: "/apis/resources/v1beta1/"}, 262 }, 263 apisTested: apiArray{ 264 {Method: "GET", URL: "/apis/resources/v1/"}, 265 {Method: "GET", URL: "/apis/resources/v2alpha1/"}, 266 {Method: "GET", URL: "/apis/resources/v1beta1/"}, 267 }, 268 ExpectedTested: apiArray{ 269 {Method: "GET", URL: "/apis/resources/v1beta1/"}, 270 }, 271 ExpectedAll: apiArray{ 272 {Method: "GET", URL: "/apis/resources/v1beta1/"}, 273 {Method: "POST", URL: "/apis/resources/v1beta1/"}, 274 }, 275 }, 276 { 277 //Test Stable APIs are returned 278 Negative: true, 279 Reg: reNotStableAPI, 280 apisOpenapi: apiArray{ 281 {Method: "GET", URL: "/apis/resources/v1/"}, 282 {Method: "POST", URL: "/apis/resources/v1/"}, 283 {Method: "GET", URL: "/apis/resources/v2alpha1/"}, 284 {Method: "POST", URL: "/apis/resources/v2alpha1/"}, 285 {Method: "GET", URL: "/apis/resources/v1beta1/"}, 286 {Method: "POST", URL: "/apis/resources/v1beta1/"}, 287 }, 288 apisTested: apiArray{ 289 {Method: "GET", URL: "/apis/resources/v1/"}, 290 {Method: "GET", URL: "/apis/resources/v2alpha1/"}, 291 {Method: "GET", URL: "/apis/resources/v1beta1/"}, 292 }, 293 ExpectedTested: apiArray{ 294 {Method: "GET", URL: "/apis/resources/v1/"}, 295 }, 296 ExpectedAll: apiArray{ 297 {Method: "GET", URL: "/apis/resources/v1/"}, 298 {Method: "POST", URL: "/apis/resources/v1/"}, 299 }, 300 }, 301 } 302 for _, test := range testCases { 303 resTested, resAll := getTestedAPIsByLevel(test.Negative, test.Reg, test.apisOpenapi, test.apisTested) 304 if !equalAPIArray(resTested, test.ExpectedTested) { 305 t.Errorf("resTested did not match expected for test") 306 t.Errorf("Expected: %#v", test.ExpectedTested) 307 t.Errorf("Actual: %#v", resTested) 308 } 309 if !equalAPIArray(resAll, test.ExpectedAll) { 310 t.Errorf("resAll did not match expected for test") 311 t.Errorf("Expected: %#v", test.ExpectedAll) 312 t.Errorf("Actual: %#v", resAll) 313 } 314 } 315 }