Working through components what-changed code.

Moved comparison function for map checking to be async, removed the untyped variation as it's no longer required. Getting prepared for tests
This commit is contained in:
Dave Shanley
2022-11-14 16:57:14 -05:00
parent 1abc25a923
commit f66c77ccb5
5 changed files with 231 additions and 78 deletions

View File

@@ -4,6 +4,7 @@
package model
import (
"github.com/pb33f/libopenapi/datamodel/low"
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
"reflect"
@@ -14,7 +15,7 @@ type ComponentsChanges struct {
SchemaChanges map[string]*SchemaChanges
ResponsesChanges map[string]*ResponseChanges
ParameterChanges map[string]*ParameterChanges
ExamplesChanges map[string]*ExamplesChanges
ExamplesChanges map[string]*ExampleChanges
RequestBodyChanges map[string]*RequestBodyChanges
HeaderChanges map[string]*HeaderChanges
SecuritySchemeChanges map[string]*SecuritySchemeChanges
@@ -34,8 +35,8 @@ func CompareComponents(l, r any) *ComponentsChanges {
reflect.TypeOf(&v2.ParameterDefinitions{}) == reflect.TypeOf(r) {
lDef := l.(*v2.ParameterDefinitions)
rDef := r.(*v2.ParameterDefinitions)
cc.ParameterChanges = CheckMapForChangesUntyped(lDef.Definitions, rDef.Definitions, &changes,
v3.ParametersLabel, CompareParameters)
cc.ParameterChanges = CheckMapForChanges(lDef.Definitions, rDef.Definitions, &changes,
v3.ParametersLabel, CompareParametersV2)
}
// Swagger Responses
@@ -43,8 +44,8 @@ func CompareComponents(l, r any) *ComponentsChanges {
reflect.TypeOf(&v2.ResponsesDefinitions{}) == reflect.TypeOf(r) {
lDef := l.(*v2.ResponsesDefinitions)
rDef := r.(*v2.ResponsesDefinitions)
cc.ResponsesChanges = CheckMapForChangesUntyped(lDef.Definitions, rDef.Definitions, &changes,
v3.ResponsesLabel, CompareResponse)
cc.ResponsesChanges = CheckMapForChanges(lDef.Definitions, rDef.Definitions, &changes,
v3.ResponsesLabel, CompareResponseV2)
}
// Swagger Schemas
@@ -61,8 +62,121 @@ func CompareComponents(l, r any) *ComponentsChanges {
reflect.TypeOf(&v2.SecurityDefinitions{}) == reflect.TypeOf(r) {
lDef := l.(*v2.SecurityDefinitions)
rDef := r.(*v2.SecurityDefinitions)
cc.SecuritySchemeChanges = CheckMapForChangesUntyped(lDef.Definitions, rDef.Definitions, &changes,
v3.SecurityDefinitionLabel, CompareSecuritySchemes)
cc.SecuritySchemeChanges = CheckMapForChanges(lDef.Definitions, rDef.Definitions, &changes,
v3.SecurityDefinitionLabel, CompareSecuritySchemesV2)
}
// OpenAPI Components
if reflect.TypeOf(&v3.Components{}) == reflect.TypeOf(l) &&
reflect.TypeOf(&v3.Components{}) == reflect.TypeOf(r) {
lComponents := l.(*v3.Components)
rComponents := r.(*v3.Components)
doneChan := make(chan componentComparison)
comparisons := 0
// run as fast as we can, thread all the things.
if !lComponents.Schemas.IsEmpty() || rComponents.Schemas.IsEmpty() {
comparisons++
go runComparison(lComponents.Schemas.Value, rComponents.Schemas.Value,
&changes, v3.SchemasLabel, CompareSchemas, doneChan)
}
if !lComponents.Responses.IsEmpty() || rComponents.Responses.IsEmpty() {
comparisons++
go runComparison(lComponents.Responses.Value, rComponents.Responses.Value,
&changes, v3.ResponsesLabel, CompareResponseV3, doneChan)
}
if !lComponents.Parameters.IsEmpty() || rComponents.Parameters.IsEmpty() {
comparisons++
go runComparison(lComponents.Parameters.Value, rComponents.Parameters.Value,
&changes, v3.ParametersLabel, CompareParametersV3, doneChan)
}
if !lComponents.Examples.IsEmpty() || rComponents.Examples.IsEmpty() {
comparisons++
go runComparison(lComponents.Examples.Value, rComponents.Examples.Value,
&changes, v3.ExamplesLabel, CompareExamples, doneChan)
}
if !lComponents.RequestBodies.IsEmpty() || rComponents.RequestBodies.IsEmpty() {
comparisons++
go runComparison(lComponents.RequestBodies.Value, rComponents.RequestBodies.Value,
&changes, v3.RequestBodiesLabel, CompareRequestBodies, doneChan)
}
if !lComponents.Headers.IsEmpty() || rComponents.Headers.IsEmpty() {
comparisons++
go runComparison(lComponents.Headers.Value, rComponents.Headers.Value,
&changes, v3.HeadersLabel, CompareHeadersV3, doneChan)
}
if !lComponents.SecuritySchemes.IsEmpty() || rComponents.SecuritySchemes.IsEmpty() {
comparisons++
go runComparison(lComponents.SecuritySchemes.Value, rComponents.SecuritySchemes.Value,
&changes, v3.SecuritySchemesLabel, CompareSecuritySchemesV3, doneChan)
}
if !lComponents.Links.IsEmpty() || rComponents.Links.IsEmpty() {
comparisons++
go runComparison(lComponents.Links.Value, rComponents.Links.Value,
&changes, v3.LinksLabel, CompareLinks, doneChan)
}
if !lComponents.Callbacks.IsEmpty() || rComponents.Callbacks.IsEmpty() {
comparisons++
go runComparison(lComponents.Callbacks.Value, rComponents.Callbacks.Value,
&changes, v3.CallbacksLabel, CompareCallback, doneChan)
}
cc.ExtensionChanges = CompareExtensions(lComponents.Extensions, rComponents.Extensions)
completedComponents := 0
for completedComponents < comparisons {
select {
case res := <-doneChan:
switch res.prop {
case v3.SchemasLabel:
completedComponents++
cc.SchemaChanges = res.result.(map[string]*SchemaChanges)
break
case v3.ResponsesLabel:
completedComponents++
cc.ResponsesChanges = res.result.(map[string]*ResponseChanges)
break
case v3.ParametersLabel:
completedComponents++
cc.ParameterChanges = res.result.(map[string]*ParameterChanges)
break
case v3.ExamplesLabel:
completedComponents++
cc.ExamplesChanges = res.result.(map[string]*ExampleChanges)
break
case v3.RequestBodiesLabel:
completedComponents++
cc.RequestBodyChanges = res.result.(map[string]*RequestBodyChanges)
break
case v3.HeadersLabel:
completedComponents++
cc.HeaderChanges = res.result.(map[string]*HeaderChanges)
break
case v3.SecuritySchemesLabel:
completedComponents++
cc.SecuritySchemeChanges = res.result.(map[string]*SecuritySchemeChanges)
break
case v3.LinksLabel:
completedComponents++
cc.LinkChanges = res.result.(map[string]*LinkChanges)
break
case v3.CallbacksLabel:
completedComponents++
cc.CallbackChanges = res.result.(map[string]*CallbackChanges)
break
}
}
}
}
cc.Changes = changes
@@ -72,6 +186,20 @@ func CompareComponents(l, r any) *ComponentsChanges {
return cc
}
type componentComparison struct {
prop string
result any
}
// run a generic comparison in a thread which in turn splits checks into further threads.
func runComparison[T any, R any](l, r map[low.KeyReference[string]]low.ValueReference[T],
changes *[]*Change, label string, compareFunc func(l, r T) R, doneChan chan componentComparison) {
doneChan <- componentComparison{
prop: label,
result: CheckMapForChanges(l, r, changes, label, compareFunc),
}
}
func (c *ComponentsChanges) TotalChanges() int {
v := c.PropertyChanges.TotalChanges()
for k := range c.SchemaChanges {