...

Source file src/k8s.io/kube-aggregator/pkg/controllers/openapi/aggregator/aggregator_test.go

Documentation: k8s.io/kube-aggregator/pkg/controllers/openapi/aggregator

     1  /*
     2  Copyright 2023 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 aggregator
    18  
    19  import (
    20  	"encoding/json"
    21  	"io"
    22  	"net/http"
    23  	"net/http/httptest"
    24  	"testing"
    25  	"time"
    26  
    27  	"bytes"
    28  
    29  	v1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
    30  	"k8s.io/kube-openapi/pkg/common"
    31  	"k8s.io/kube-openapi/pkg/validation/spec"
    32  )
    33  
    34  func TestBasicPathsMerged(t *testing.T) {
    35  	mux := http.NewServeMux()
    36  	delegationHandlers := []http.Handler{
    37  		&openAPIHandler{
    38  			openapi: &spec.Swagger{
    39  				SwaggerProps: spec.SwaggerProps{
    40  					Paths: &spec.Paths{
    41  						Paths: map[string]spec.PathItem{
    42  							"/apis/foo/v1/": {},
    43  						},
    44  					},
    45  				},
    46  			},
    47  		},
    48  	}
    49  	buildAndRegisterSpecAggregator(delegationHandlers, mux)
    50  
    51  	swagger, err := fetchOpenAPI(mux)
    52  	if err != nil {
    53  		t.Error(err)
    54  	}
    55  	expectPath(t, swagger, "/apis/foo/v1/")
    56  	expectPath(t, swagger, "/apis/apiregistration.k8s.io/v1/")
    57  }
    58  
    59  func TestAddUpdateAPIService(t *testing.T) {
    60  	mux := http.NewServeMux()
    61  	var delegationHandlers []http.Handler
    62  	delegate1 := &openAPIHandler{openapi: &spec.Swagger{
    63  		SwaggerProps: spec.SwaggerProps{
    64  			Paths: &spec.Paths{
    65  				Paths: map[string]spec.PathItem{
    66  					"/apis/foo/v1": {},
    67  				},
    68  			},
    69  		},
    70  	}}
    71  	delegationHandlers = append(delegationHandlers, delegate1)
    72  	s := buildAndRegisterSpecAggregator(delegationHandlers, mux)
    73  
    74  	apiService := &v1.APIService{
    75  		Spec: v1.APIServiceSpec{
    76  			Group:   "apiservicegroup",
    77  			Version: "v1",
    78  			Service: &v1.ServiceReference{Name: "dummy"},
    79  		},
    80  	}
    81  	apiService.Name = "apiservice"
    82  
    83  	handler := &openAPIHandler{openapi: &spec.Swagger{
    84  		SwaggerProps: spec.SwaggerProps{
    85  			Paths: &spec.Paths{
    86  				Paths: map[string]spec.PathItem{
    87  					"/apis/apiservicegroup/v1/path1": {},
    88  				},
    89  			},
    90  		},
    91  	}}
    92  
    93  	if err := s.AddUpdateAPIService(apiService, handler); err != nil {
    94  		t.Error(err)
    95  	}
    96  	if err := s.UpdateAPIServiceSpec(apiService.Name); err != nil {
    97  		t.Error(err)
    98  	}
    99  
   100  	swagger, err := fetchOpenAPI(mux)
   101  	if err != nil {
   102  		t.Error(err)
   103  	}
   104  
   105  	expectPath(t, swagger, "/apis/apiservicegroup/v1/path1")
   106  	expectPath(t, swagger, "/apis/apiregistration.k8s.io/v1/")
   107  
   108  	t.Log("Update APIService OpenAPI")
   109  	handler.openapi = &spec.Swagger{
   110  		SwaggerProps: spec.SwaggerProps{
   111  			Paths: &spec.Paths{
   112  				Paths: map[string]spec.PathItem{
   113  					"/apis/apiservicegroup/v1/path2": {},
   114  				},
   115  			},
   116  		},
   117  	}
   118  	if err := s.UpdateAPIServiceSpec(apiService.Name); err != nil {
   119  		t.Error(err)
   120  	}
   121  
   122  	swagger, err = fetchOpenAPI(mux)
   123  	if err != nil {
   124  		t.Error(err)
   125  	}
   126  	// Ensure that the if the APIService OpenAPI is updated, the
   127  	// aggregated OpenAPI is also updated.
   128  	expectPath(t, swagger, "/apis/apiservicegroup/v1/path2")
   129  	expectNoPath(t, swagger, "/apis/apiservicegroup/v1/path1")
   130  	expectPath(t, swagger, "/apis/apiregistration.k8s.io/v1/")
   131  }
   132  
   133  // Tests that an APIService that registers OpenAPI will only have the OpenAPI
   134  // for its specific group version served registered.
   135  // See https://github.com/kubernetes/kubernetes/pull/123570 for full context.
   136  func TestAPIServiceOpenAPIServiceMismatch(t *testing.T) {
   137  	mux := http.NewServeMux()
   138  	var delegationHandlers []http.Handler
   139  	delegate1 := &openAPIHandler{openapi: &spec.Swagger{
   140  		SwaggerProps: spec.SwaggerProps{
   141  			Paths: &spec.Paths{
   142  				Paths: map[string]spec.PathItem{
   143  					"/apis/foo/v1/": {},
   144  				},
   145  			},
   146  		},
   147  	}}
   148  	delegationHandlers = append(delegationHandlers, delegate1)
   149  
   150  	s := buildAndRegisterSpecAggregator(delegationHandlers, mux)
   151  
   152  	apiService := &v1.APIService{
   153  		Spec: v1.APIServiceSpec{
   154  			Group:   "apiservicegroup",
   155  			Version: "v1",
   156  			Service: &v1.ServiceReference{Name: "dummy"},
   157  		},
   158  	}
   159  	apiService.Name = "apiservice"
   160  
   161  	apiService2 := &v1.APIService{
   162  		Spec: v1.APIServiceSpec{
   163  			Group:   "apiservicegroup",
   164  			Version: "v2",
   165  			Service: &v1.ServiceReference{Name: "dummy2"},
   166  		},
   167  	}
   168  	apiService2.Name = "apiservice2"
   169  
   170  	handler := &openAPIHandler{openapi: &spec.Swagger{
   171  		SwaggerProps: spec.SwaggerProps{
   172  			Paths: &spec.Paths{
   173  				Paths: map[string]spec.PathItem{
   174  					"/apis/apiservicegroup/v1/":      {},
   175  					"/apis/apiservicegroup/v1beta1/": {},
   176  				},
   177  			},
   178  		},
   179  	}}
   180  
   181  	handler2 := &openAPIHandler{openapi: &spec.Swagger{
   182  		SwaggerProps: spec.SwaggerProps{
   183  			Paths: &spec.Paths{
   184  				Paths: map[string]spec.PathItem{
   185  					"/apis/a/":                  {},
   186  					"/apis/apiservicegroup/v1/": {},
   187  					"/apis/apiservicegroup/v2/": {},
   188  				},
   189  			},
   190  		},
   191  	}}
   192  
   193  	if err := s.AddUpdateAPIService(apiService, handler); err != nil {
   194  		t.Error(err)
   195  	}
   196  	if err := s.UpdateAPIServiceSpec(apiService.Name); err != nil {
   197  		t.Error(err)
   198  	}
   199  
   200  	if err := s.AddUpdateAPIService(apiService2, handler2); err != nil {
   201  		t.Error(err)
   202  	}
   203  	if err := s.UpdateAPIServiceSpec(apiService2.Name); err != nil {
   204  		t.Error(err)
   205  	}
   206  
   207  	swagger, err := fetchOpenAPI(mux)
   208  	if err != nil {
   209  		t.Error(err)
   210  	}
   211  	expectPath(t, swagger, "/apis/apiservicegroup/v1/")
   212  	expectPath(t, swagger, "/apis/apiservicegroup/v2/")
   213  	expectPath(t, swagger, "/apis/apiregistration.k8s.io/v1/")
   214  	expectNoPath(t, swagger, "/apis/a/")
   215  	expectNoPath(t, swagger, "/apis/apiservicegroup/v1beta1/")
   216  
   217  	t.Logf("Remove APIService %s", apiService.Name)
   218  	s.RemoveAPIService(apiService.Name)
   219  
   220  	swagger, err = fetchOpenAPI(mux)
   221  	if err != nil {
   222  		t.Error(err)
   223  	}
   224  	// Ensure that the if the APIService is added then removed, the OpenAPI disappears from the aggregated OpenAPI as well.
   225  	expectNoPath(t, swagger, "/apis/apiservicegroup/v1")
   226  	expectPath(t, swagger, "/apis/apiregistration.k8s.io/v1/")
   227  	expectNoPath(t, swagger, "/apis/a")
   228  }
   229  
   230  func TestAddRemoveAPIService(t *testing.T) {
   231  	mux := http.NewServeMux()
   232  	var delegationHandlers []http.Handler
   233  	delegate1 := &openAPIHandler{openapi: &spec.Swagger{
   234  		SwaggerProps: spec.SwaggerProps{
   235  			Paths: &spec.Paths{
   236  				Paths: map[string]spec.PathItem{
   237  					"/apis/foo/v1/": {},
   238  				},
   239  			},
   240  		},
   241  	}}
   242  	delegationHandlers = append(delegationHandlers, delegate1)
   243  
   244  	s := buildAndRegisterSpecAggregator(delegationHandlers, mux)
   245  
   246  	apiService := &v1.APIService{
   247  		Spec: v1.APIServiceSpec{
   248  			Group:   "apiservicegroup",
   249  			Version: "v1",
   250  			Service: &v1.ServiceReference{Name: "dummy"},
   251  		},
   252  	}
   253  	apiService.Name = "apiservice"
   254  
   255  	handler := &openAPIHandler{openapi: &spec.Swagger{
   256  		SwaggerProps: spec.SwaggerProps{
   257  			Paths: &spec.Paths{
   258  				Paths: map[string]spec.PathItem{
   259  					"/apis/apiservicegroup/v1/": {},
   260  				},
   261  			},
   262  		},
   263  	}}
   264  
   265  	if err := s.AddUpdateAPIService(apiService, handler); err != nil {
   266  		t.Error(err)
   267  	}
   268  	if err := s.UpdateAPIServiceSpec(apiService.Name); err != nil {
   269  		t.Error(err)
   270  	}
   271  
   272  	swagger, err := fetchOpenAPI(mux)
   273  	if err != nil {
   274  		t.Error(err)
   275  	}
   276  	expectPath(t, swagger, "/apis/apiservicegroup/v1/")
   277  	expectPath(t, swagger, "/apis/apiregistration.k8s.io/v1/")
   278  
   279  	t.Logf("Remove APIService %s", apiService.Name)
   280  	s.RemoveAPIService(apiService.Name)
   281  
   282  	swagger, err = fetchOpenAPI(mux)
   283  	if err != nil {
   284  		t.Error(err)
   285  	}
   286  	// Ensure that the if the APIService is added then removed, the OpenAPI disappears from the aggregated OpenAPI as well.
   287  	expectNoPath(t, swagger, "/apis/apiservicegroup/v1/")
   288  	expectPath(t, swagger, "/apis/apiregistration.k8s.io/v1/")
   289  }
   290  
   291  func TestUpdateAPIService(t *testing.T) {
   292  	mux := http.NewServeMux()
   293  	var delegationHandlers []http.Handler
   294  	delegate1 := &openAPIHandler{openapi: &spec.Swagger{
   295  		SwaggerProps: spec.SwaggerProps{
   296  			Paths: &spec.Paths{
   297  				Paths: map[string]spec.PathItem{
   298  					"/apis/foo/v1/": {},
   299  				},
   300  			},
   301  		},
   302  	}}
   303  	delegationHandlers = append(delegationHandlers, delegate1)
   304  
   305  	s := buildAndRegisterSpecAggregator(delegationHandlers, mux)
   306  
   307  	apiService := &v1.APIService{
   308  		Spec: v1.APIServiceSpec{
   309  			Group:   "apiservicegroup",
   310  			Version: "v1",
   311  			Service: &v1.ServiceReference{Name: "dummy"},
   312  		},
   313  	}
   314  	apiService.Name = "apiservice"
   315  
   316  	handler := &openAPIHandler{openapi: &spec.Swagger{
   317  		SwaggerProps: spec.SwaggerProps{
   318  			Paths: &spec.Paths{
   319  				Paths: map[string]spec.PathItem{
   320  					"/apis/apiservicegroup/v1/": {},
   321  				},
   322  			},
   323  		},
   324  	}}
   325  
   326  	handler2 := &openAPIHandler{openapi: &spec.Swagger{
   327  		SwaggerProps: spec.SwaggerProps{
   328  			Paths: &spec.Paths{
   329  				Paths: map[string]spec.PathItem{},
   330  			},
   331  		},
   332  	}}
   333  
   334  	if err := s.AddUpdateAPIService(apiService, handler); err != nil {
   335  		t.Error(err)
   336  	}
   337  	if err := s.UpdateAPIServiceSpec(apiService.Name); err != nil {
   338  		t.Error(err)
   339  	}
   340  
   341  	swagger, err := fetchOpenAPI(mux)
   342  	if err != nil {
   343  		t.Error(err)
   344  	}
   345  	expectPath(t, swagger, "/apis/apiservicegroup/v1/")
   346  	expectPath(t, swagger, "/apis/apiregistration.k8s.io/v1/")
   347  
   348  	t.Logf("Updating APIService %s", apiService.Name)
   349  	if err := s.AddUpdateAPIService(apiService, handler2); err != nil {
   350  		t.Error(err)
   351  	}
   352  	if err := s.UpdateAPIServiceSpec(apiService.Name); err != nil {
   353  		t.Error(err)
   354  	}
   355  
   356  	swagger, err = fetchOpenAPI(mux)
   357  	if err != nil {
   358  		t.Error(err)
   359  	}
   360  	// Ensure that the if the APIService is added and then handler is modified, the new data is reflected in the aggregated OpenAPI.
   361  	expectNoPath(t, swagger, "/apis/apiservicegroup/v1/")
   362  	expectPath(t, swagger, "/apis/apiregistration.k8s.io/v1/")
   363  }
   364  
   365  func TestFailingAPIServiceSkippedAggregation(t *testing.T) {
   366  	mux := http.NewServeMux()
   367  	var delegationHandlers []http.Handler
   368  	delegate1 := &openAPIHandler{openapi: &spec.Swagger{
   369  		SwaggerProps: spec.SwaggerProps{
   370  			Paths: &spec.Paths{
   371  				Paths: map[string]spec.PathItem{
   372  					"/apis/foo/v1/": {},
   373  				},
   374  			},
   375  		},
   376  	}}
   377  	delegationHandlers = append(delegationHandlers, delegate1)
   378  
   379  	s := buildAndRegisterSpecAggregator(delegationHandlers, mux)
   380  
   381  	apiServiceFailed := &v1.APIService{
   382  		Spec: v1.APIServiceSpec{
   383  			Group:   "failed",
   384  			Version: "v1",
   385  			Service: &v1.ServiceReference{Name: "dummy"},
   386  		},
   387  	}
   388  	apiServiceFailed.Name = "apiserviceFailed"
   389  
   390  	handlerFailed := &openAPIHandler{
   391  		returnErr: true,
   392  		openapi: &spec.Swagger{
   393  			SwaggerProps: spec.SwaggerProps{
   394  				Paths: &spec.Paths{
   395  					Paths: map[string]spec.PathItem{
   396  						"/apis/failed/v1/": {},
   397  					},
   398  				},
   399  			},
   400  		},
   401  	}
   402  
   403  	apiServiceSuccess := &v1.APIService{
   404  		Spec: v1.APIServiceSpec{
   405  			Group:   "success",
   406  			Version: "v1",
   407  			Service: &v1.ServiceReference{Name: "dummy2"},
   408  		},
   409  	}
   410  	apiServiceSuccess.Name = "apiserviceSuccess"
   411  
   412  	handlerSuccess := &openAPIHandler{
   413  		openapi: &spec.Swagger{
   414  			SwaggerProps: spec.SwaggerProps{
   415  				Paths: &spec.Paths{
   416  					Paths: map[string]spec.PathItem{
   417  						"/apis/success/v1/": {},
   418  					},
   419  				},
   420  			},
   421  		},
   422  	}
   423  
   424  	if err := s.AddUpdateAPIService(apiServiceSuccess, handlerSuccess); err != nil {
   425  		t.Error(err)
   426  	}
   427  	if err := s.AddUpdateAPIService(apiServiceFailed, handlerFailed); err != nil {
   428  		t.Error(err)
   429  	}
   430  	if err := s.UpdateAPIServiceSpec(apiServiceSuccess.Name); err != nil {
   431  		t.Error(err)
   432  	}
   433  	err := s.UpdateAPIServiceSpec(apiServiceFailed.Name)
   434  	if err == nil {
   435  		t.Errorf("Expected updating failing apiService %s to return error", apiServiceFailed.Name)
   436  	}
   437  
   438  	swagger, err := fetchOpenAPI(mux)
   439  	if err != nil {
   440  		t.Error(err)
   441  	}
   442  	expectPath(t, swagger, "/apis/foo/v1/")
   443  	expectNoPath(t, swagger, "/apis/failed/v1/")
   444  	expectPath(t, swagger, "/apis/success/v1/")
   445  }
   446  
   447  func TestAPIServiceFailSuccessTransition(t *testing.T) {
   448  	mux := http.NewServeMux()
   449  	var delegationHandlers []http.Handler
   450  	delegate1 := &openAPIHandler{openapi: &spec.Swagger{
   451  		SwaggerProps: spec.SwaggerProps{
   452  			Paths: &spec.Paths{
   453  				Paths: map[string]spec.PathItem{
   454  					"/apis/foo/v1/": {},
   455  				},
   456  			},
   457  		},
   458  	}}
   459  	delegationHandlers = append(delegationHandlers, delegate1)
   460  
   461  	s := buildAndRegisterSpecAggregator(delegationHandlers, mux)
   462  
   463  	apiService := &v1.APIService{
   464  		Spec: v1.APIServiceSpec{
   465  			Group:   "apiservicegroup",
   466  			Version: "v1",
   467  			Service: &v1.ServiceReference{Name: "dummy"},
   468  		},
   469  	}
   470  	apiService.Name = "apiservice"
   471  
   472  	handler := &openAPIHandler{
   473  		returnErr: true,
   474  		openapi: &spec.Swagger{
   475  			SwaggerProps: spec.SwaggerProps{
   476  				Paths: &spec.Paths{
   477  					Paths: map[string]spec.PathItem{
   478  						"/apis/apiservicegroup/v1/": {},
   479  					},
   480  				},
   481  			},
   482  		},
   483  	}
   484  
   485  	if err := s.AddUpdateAPIService(apiService, handler); err != nil {
   486  		t.Error(err)
   487  	}
   488  	if err := s.UpdateAPIServiceSpec(apiService.Name); err == nil {
   489  		t.Errorf("Expected error for when updating spec for failing apiservice")
   490  	}
   491  
   492  	swagger, err := fetchOpenAPI(mux)
   493  	if err != nil {
   494  		t.Error(err)
   495  	}
   496  	expectPath(t, swagger, "/apis/foo/v1/")
   497  	expectNoPath(t, swagger, "/apis/apiservicegroup/v1/")
   498  
   499  	t.Log("Transition APIService to not return error")
   500  	handler.returnErr = false
   501  	err = s.UpdateAPIServiceSpec(apiService.Name)
   502  	if err != nil {
   503  		t.Error(err)
   504  	}
   505  	swagger, err = fetchOpenAPI(mux)
   506  	if err != nil {
   507  		t.Error(err)
   508  	}
   509  	expectPath(t, swagger, "/apis/foo/v1/")
   510  	expectPath(t, swagger, "/apis/apiservicegroup/v1/")
   511  }
   512  
   513  func TestFailingAPIServiceDoesNotBlockAdd(t *testing.T) {
   514  	mux := http.NewServeMux()
   515  	var delegationHandlers []http.Handler
   516  	delegate1 := &openAPIHandler{openapi: &spec.Swagger{
   517  		SwaggerProps: spec.SwaggerProps{
   518  			Paths: &spec.Paths{
   519  				Paths: map[string]spec.PathItem{
   520  					"/apis/foo/v1/": {},
   521  				},
   522  			},
   523  		},
   524  	}}
   525  	delegationHandlers = append(delegationHandlers, delegate1)
   526  
   527  	s := buildAndRegisterSpecAggregator(delegationHandlers, mux)
   528  
   529  	apiServiceFailed := &v1.APIService{
   530  		Spec: v1.APIServiceSpec{
   531  			Group:   "failed",
   532  			Version: "v1",
   533  			Service: &v1.ServiceReference{Name: "dummy"},
   534  		},
   535  	}
   536  	apiServiceFailed.Name = "apiserviceFailed"
   537  
   538  	// Create a handler that has a long response time and ensure that
   539  	// adding the APIService does not block.
   540  	handlerFailed := &openAPIHandler{
   541  		delaySeconds: 5,
   542  		returnErr:    true,
   543  		openapi: &spec.Swagger{
   544  			SwaggerProps: spec.SwaggerProps{
   545  				Paths: &spec.Paths{
   546  					Paths: map[string]spec.PathItem{
   547  						"/apis/failed/v1/": {},
   548  					},
   549  				},
   550  			},
   551  		},
   552  	}
   553  
   554  	updateDone := make(chan bool)
   555  	go func() {
   556  		if err := s.AddUpdateAPIService(apiServiceFailed, handlerFailed); err != nil {
   557  			t.Error(err)
   558  		}
   559  		close(updateDone)
   560  	}()
   561  
   562  	select {
   563  	case <-updateDone:
   564  	case <-time.After(2 * time.Second):
   565  		t.Errorf("AddUpdateAPIService affected by APIService response time")
   566  	}
   567  
   568  	swagger, err := fetchOpenAPI(mux)
   569  	if err != nil {
   570  		t.Error(err)
   571  	}
   572  	expectPath(t, swagger, "/apis/foo/v1/")
   573  	expectNoPath(t, swagger, "/apis/failed/v1/")
   574  }
   575  
   576  type openAPIHandler struct {
   577  	delaySeconds int
   578  	openapi      *spec.Swagger
   579  	returnErr    bool
   580  }
   581  
   582  func (o *openAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   583  	time.Sleep(time.Duration(o.delaySeconds) * time.Second)
   584  	if o.returnErr {
   585  		w.WriteHeader(500)
   586  		return
   587  	}
   588  	data, err := json.Marshal(o.openapi)
   589  	if err != nil {
   590  		panic(err)
   591  	}
   592  	http.ServeContent(w, r, "/openapi/v2", time.Now(), bytes.NewReader(data))
   593  	return
   594  }
   595  
   596  func fetchOpenAPI(mux *http.ServeMux) (*spec.Swagger, error) {
   597  	server := httptest.NewServer(mux)
   598  	defer server.Close()
   599  	client := server.Client()
   600  
   601  	req, err := http.NewRequest("GET", server.URL+"/openapi/v2", nil)
   602  	if err != nil {
   603  		return nil, err
   604  	}
   605  	resp, err := client.Do(req)
   606  	if err != nil {
   607  		return nil, err
   608  	}
   609  	body, err := io.ReadAll(resp.Body)
   610  
   611  	swagger := &spec.Swagger{}
   612  	if err := swagger.UnmarshalJSON(body); err != nil {
   613  		return nil, err
   614  	}
   615  	return swagger, err
   616  }
   617  
   618  func buildAndRegisterSpecAggregator(delegationHandlers []http.Handler, mux common.PathHandler) *specAggregator {
   619  	downloader := NewDownloader()
   620  	aggregatorSpec := &spec.Swagger{
   621  		SwaggerProps: spec.SwaggerProps{
   622  			Paths: &spec.Paths{
   623  				Paths: map[string]spec.PathItem{
   624  					"/apis/apiregistration.k8s.io/v1/": {},
   625  				},
   626  			},
   627  		},
   628  	}
   629  	s := buildAndRegisterSpecAggregatorForLocalServices(&downloader, aggregatorSpec, delegationHandlers, mux)
   630  	return s
   631  }
   632  
   633  func expectPath(t *testing.T, swagger *spec.Swagger, path string) {
   634  	if _, ok := swagger.Paths.Paths[path]; !ok {
   635  		t.Errorf("Expected path %s to exist in aggregated paths", path)
   636  	}
   637  }
   638  
   639  func expectNoPath(t *testing.T, swagger *spec.Swagger, path string) {
   640  	if _, ok := swagger.Paths.Paths[path]; ok {
   641  		t.Errorf("Expected path %s to be omitted in aggregated paths", path)
   642  	}
   643  }
   644  

View as plain text