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  }