fix: continued moving everything to orderedmaps plus cleaned up most the tests

This commit is contained in:
Tristan Cartledge
2023-12-01 17:37:07 +00:00
parent 0f3d0cb28f
commit a4ad09aab3
169 changed files with 3435 additions and 3764 deletions

View File

@@ -56,7 +56,6 @@ func (c *CallbackChanges) TotalBreakingChanges() int {
// CompareCallback will compare two Callback objects and return a pointer to CallbackChanges with all the things
// that have changed between them.
func CompareCallback(l, r *v3.Callback) *CallbackChanges {
cc := new(CallbackChanges)
var changes []*Change
@@ -66,12 +65,12 @@ func CompareCallback(l, r *v3.Callback) *CallbackChanges {
lValues := make(map[string]low.ValueReference[*v3.PathItem])
rValues := make(map[string]low.ValueReference[*v3.PathItem])
for pair := orderedmap.First(l.Expression.Value); pair != nil; pair = pair.Next() {
for pair := orderedmap.First(l.Expression); pair != nil; pair = pair.Next() {
lHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
lValues[pair.Key().Value] = pair.Value()
}
for pair := orderedmap.First(r.Expression.Value); pair != nil; pair = pair.Next() {
for pair := orderedmap.First(r.Expression); pair != nil; pair = pair.Next() {
rHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
rValues[pair.Key().Value] = pair.Value()
}
@@ -94,7 +93,7 @@ func CompareCallback(l, r *v3.Callback) *CallbackChanges {
expChanges[k] = ComparePathItems(lValues[k].Value, rValues[k].Value)
}
//check right path item hashes
// check right path item hashes
for k := range rHashes {
lhash := lHashes[k]
if lhash == "" {

View File

@@ -82,7 +82,7 @@ func FlattenLowLevelMap[T any](
}
func FlattenLowLevelOrderedMap[T any](
lowMap orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
lowMap *orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
) map[string]*low.ValueReference[T] {
flat := make(map[string]*low.ValueReference[T])
@@ -252,13 +252,13 @@ func CheckForModification[T any](l, r *yaml.Node, label string, changes *[]*Chan
// CheckMapForChanges checks a left and right low level map for any additions, subtractions or modifications to
// values. The compareFunc argument should reference the correct comparison function for the generic type.
func CheckMapForChanges[T any, R any](expLeft, expRight orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
func CheckMapForChanges[T any, R any](expLeft, expRight *orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
changes *[]*Change, label string, compareFunc func(l, r T) R,
) map[string]R {
return CheckMapForChangesWithComp(expLeft, expRight, changes, label, compareFunc, true)
}
func CheckMapForAdditionRemoval[T any](expLeft, expRight orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
func CheckMapForAdditionRemoval[T any](expLeft, expRight *orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
changes *[]*Change, label string,
) any {
// do nothing
@@ -282,7 +282,7 @@ func CheckMapForAdditionRemoval[T any](expLeft, expRight orderedmap.Map[low.KeyR
// CheckMapForChangesWithComp checks a left and right low level map for any additions, subtractions or modifications to
// values. The compareFunc argument should reference the correct comparison function for the generic type. The compare
// bit determines if the comparison should be run or not.
func CheckMapForChangesWithComp[T any, R any](expLeft, expRight orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
func CheckMapForChangesWithComp[T any, R any](expLeft, expRight *orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
changes *[]*Change, label string, compareFunc func(l, r T) R, compare bool,
) map[string]R {
// stop concurrent threads screwing up changes.
@@ -420,20 +420,28 @@ func ExtractStringValueSliceChanges(lParam, rParam []low.ValueReference[string],
}
}
func toString(v any) string {
if y, ok := v.(*yaml.Node); ok {
_ = y.Encode(&v)
}
return fmt.Sprint(v)
}
// ExtractRawValueSliceChanges will compare two low level interface{} slices for changes.
func ExtractRawValueSliceChanges(lParam, rParam []low.ValueReference[any],
func ExtractRawValueSliceChanges[T any](lParam, rParam []low.ValueReference[T],
changes *[]*Change, label string, breaking bool,
) {
lKeys := make([]string, len(lParam))
rKeys := make([]string, len(rParam))
lValues := make(map[string]low.ValueReference[any])
rValues := make(map[string]low.ValueReference[any])
lValues := make(map[string]low.ValueReference[T])
rValues := make(map[string]low.ValueReference[T])
for i := range lParam {
lKeys[i] = strings.ToLower(fmt.Sprint(lParam[i].Value))
lKeys[i] = strings.ToLower(toString(lParam[i].Value))
lValues[lKeys[i]] = lParam[i]
}
for i := range rParam {
rKeys[i] = strings.ToLower(fmt.Sprint(rParam[i].Value))
rKeys[i] = strings.ToLower(toString(rParam[i].Value))
rValues[rKeys[i]] = rParam[i]
}
for i := range lValues {

View File

@@ -46,7 +46,6 @@ type ComponentsChanges struct {
// CompareComponents will compare OpenAPI components for any changes. Accepts Swagger Definition objects
// like ParameterDefinitions or Definitions etc.
func CompareComponents(l, r any) *ComponentsChanges {
var changes []*Change
cc := new(ComponentsChanges)
@@ -56,7 +55,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
reflect.TypeOf(&v2.ParameterDefinitions{}) == reflect.TypeOf(r) {
lDef := l.(*v2.ParameterDefinitions)
rDef := r.(*v2.ParameterDefinitions)
var a, b orderedmap.Map[low.KeyReference[string], low.ValueReference[*v2.Parameter]]
var a, b *orderedmap.Map[low.KeyReference[string], low.ValueReference[*v2.Parameter]]
if lDef != nil {
a = lDef.Definitions
}
@@ -71,7 +70,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
reflect.TypeOf(&v2.ResponsesDefinitions{}) == reflect.TypeOf(r) {
lDef := l.(*v2.ResponsesDefinitions)
rDef := r.(*v2.ResponsesDefinitions)
var a, b orderedmap.Map[low.KeyReference[string], low.ValueReference[*v2.Response]]
var a, b *orderedmap.Map[low.KeyReference[string], low.ValueReference[*v2.Response]]
if lDef != nil {
a = lDef.Definitions
}
@@ -86,7 +85,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
reflect.TypeOf(&v2.Definitions{}) == reflect.TypeOf(r) {
lDef := l.(*v2.Definitions)
rDef := r.(*v2.Definitions)
var a, b orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]]
var a, b *orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]]
if lDef != nil {
a = lDef.Schemas
}
@@ -101,7 +100,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
reflect.TypeOf(&v2.SecurityDefinitions{}) == reflect.TypeOf(r) {
lDef := l.(*v2.SecurityDefinitions)
rDef := r.(*v2.SecurityDefinitions)
var a, b orderedmap.Map[low.KeyReference[string], low.ValueReference[*v2.SecurityScheme]]
var a, b *orderedmap.Map[low.KeyReference[string], low.ValueReference[*v2.SecurityScheme]]
if lDef != nil {
a = lDef.Definitions
}
@@ -218,9 +217,9 @@ type componentComparison struct {
}
// run a generic comparison in a thread which in turn splits checks into further threads.
func runComparison[T any, R any](l, r orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
changes *[]*Change, label string, compareFunc func(l, r T) R, doneChan chan componentComparison) {
func runComparison[T any, R any](l, r *orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
changes *[]*Change, label string, compareFunc func(l, r T) R, doneChan chan componentComparison,
) {
// for schemas
if label == v3.SchemasLabel || label == v2.DefinitionsLabel || label == v3.SecuritySchemesLabel {
doneChan <- componentComparison{

View File

@@ -35,6 +35,10 @@ type DocumentChanges struct {
// TotalChanges returns a total count of all changes made in the Document
func (d *DocumentChanges) TotalChanges() int {
if d == nil {
return 0
}
c := d.PropertyChanges.TotalChanges()
if d.InfoChanges != nil {
c += d.InfoChanges.TotalChanges()
@@ -68,6 +72,10 @@ func (d *DocumentChanges) TotalChanges() int {
// GetAllChanges returns a slice of all changes made between Document objects
func (d *DocumentChanges) GetAllChanges() []*Change {
if d == nil {
return nil
}
var changes []*Change
changes = append(changes, d.Changes...)
if d.InfoChanges != nil {
@@ -133,7 +141,6 @@ func (d *DocumentChanges) TotalBreakingChanges() int {
// CompareDocuments will compare any two OpenAPI documents (either Swagger or OpenAPI) and return a pointer to
// DocumentChanges that outlines everything that was found to have changed.
func CompareDocuments(l, r any) *DocumentChanges {
var changes []*Change
var props []*PropertyCheck

View File

@@ -7,6 +7,7 @@ import (
"github.com/pb33f/libopenapi/datamodel/low"
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
"github.com/pb33f/libopenapi/orderedmap"
"gopkg.in/yaml.v3"
)
// ExamplesChanges represents changes made between Swagger Examples objects (Not OpenAPI 3).
@@ -32,11 +33,10 @@ func (a *ExamplesChanges) TotalBreakingChanges() int {
// CompareExamplesV2 compares two Swagger Examples objects, returning a pointer to
// ExamplesChanges if anything was found.
func CompareExamplesV2(l, r *v2.Examples) *ExamplesChanges {
lHashes := make(map[string]string)
rHashes := make(map[string]string)
lValues := make(map[string]low.ValueReference[any])
rValues := make(map[string]low.ValueReference[any])
lValues := make(map[string]low.ValueReference[*yaml.Node])
rValues := make(map[string]low.ValueReference[*yaml.Node])
for pair := orderedmap.First(l.Values); pair != nil; pair = pair.Next() {
lHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
@@ -67,7 +67,7 @@ func CompareExamplesV2(l, r *v2.Examples) *ExamplesChanges {
}
//check right example hashes
// check right example hashes
for k := range rHashes {
lhash := lHashes[k]
if lhash == "" {

View File

@@ -4,8 +4,11 @@
package model
import (
"github.com/pb33f/libopenapi/datamodel/low"
"strings"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/orderedmap"
"gopkg.in/yaml.v3"
)
// ExtensionChanges represents any changes to custom extensions defined for an OpenAPI object.
@@ -34,24 +37,24 @@ func (e *ExtensionChanges) TotalBreakingChanges() int {
//
// A current limitation relates to extensions being objects and a property of the object changes,
// there is currently no support for knowing anything changed - so it is ignored.
func CompareExtensions(l, r map[low.KeyReference[string]]low.ValueReference[any]) *ExtensionChanges {
func CompareExtensions(l, r *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]) *ExtensionChanges {
// look at the original and then look through the new.
seenLeft := make(map[string]*low.ValueReference[any])
seenRight := make(map[string]*low.ValueReference[any])
for i := range l {
h := l[i]
seenLeft[strings.ToLower(i.Value)] = &h
seenLeft := make(map[string]*low.ValueReference[*yaml.Node])
seenRight := make(map[string]*low.ValueReference[*yaml.Node])
for pair := orderedmap.First(l); pair != nil; pair = pair.Next() {
h := pair.Value()
seenLeft[strings.ToLower(pair.Key().Value)] = &h
}
for i := range r {
h := r[i]
seenRight[strings.ToLower(i.Value)] = &h
for pair := orderedmap.First(r); pair != nil; pair = pair.Next() {
h := pair.Value()
seenRight[strings.ToLower(pair.Key().Value)] = &h
}
var changes []*Change
for i := range seenLeft {
CheckForObjectAdditionOrRemoval[any](seenLeft, seenRight, i, &changes, false, true)
CheckForObjectAdditionOrRemoval[*yaml.Node](seenLeft, seenRight, i, &changes, false, true)
if seenRight[i] != nil {
var props []*PropertyCheck
@@ -72,7 +75,7 @@ func CompareExtensions(l, r map[low.KeyReference[string]]low.ValueReference[any]
}
for i := range seenRight {
if seenLeft[i] == nil {
CheckForObjectAdditionOrRemoval[any](seenLeft, seenRight, i, &changes, false, true)
CheckForObjectAdditionOrRemoval[*yaml.Node](seenLeft, seenRight, i, &changes, false, true)
}
}
ex := new(ExtensionChanges)
@@ -86,11 +89,11 @@ func CompareExtensions(l, r map[low.KeyReference[string]]low.ValueReference[any]
// CheckExtensions is a helper method to un-pack a left and right model that contains extensions. Once unpacked
// the extensions are compared and returns a pointer to ExtensionChanges. If nothing changed, nil is returned.
func CheckExtensions[T low.HasExtensions[T]](l, r T) *ExtensionChanges {
var lExt, rExt map[low.KeyReference[string]]low.ValueReference[any]
if len(l.GetExtensions()) > 0 {
var lExt, rExt *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
if orderedmap.Len(l.GetExtensions()) > 0 {
lExt = l.GetExtensions()
}
if len(r.GetExtensions()) > 0 {
if orderedmap.Len(r.GetExtensions()) > 0 {
rExt = r.GetExtensions()
}
return CompareExtensions(lExt, rExt)

View File

@@ -4,12 +4,14 @@
package model
import (
"reflect"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/datamodel/low/base"
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
"github.com/pb33f/libopenapi/orderedmap"
"gopkg.in/yaml.v3"
"reflect"
)
// ParameterChanges represents changes found between Swagger or OpenAPI Parameter objects.
@@ -222,14 +224,13 @@ func CompareParametersV3(l, r *v3.Parameter) *ParameterChanges {
// CompareParameters compares a left and right Swagger or OpenAPI Parameter object for any changes. If found returns
// a pointer to ParameterChanges. If nothing is found, returns nil.
func CompareParameters(l, r any) *ParameterChanges {
var changes []*Change
var props []*PropertyCheck
pc := new(ParameterChanges)
var lSchema *base.SchemaProxy
var rSchema *base.SchemaProxy
var lext, rext map[low.KeyReference[string]]low.ValueReference[any]
var lext, rext *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
if reflect.TypeOf(&v2.Parameter{}) == reflect.TypeOf(l) && reflect.TypeOf(&v2.Parameter{}) == reflect.TypeOf(r) {
lParam := l.(*v2.Parameter)
@@ -331,7 +332,7 @@ func CompareParameters(l, r any) *ParameterChanges {
return pc
}
func checkParameterExample(expLeft, expRight low.NodeReference[any], changes []*Change) {
func checkParameterExample(expLeft, expRight low.NodeReference[*yaml.Node], changes []*Change) {
if !expLeft.IsEmpty() && !expRight.IsEmpty() {
if low.GenerateHashString(expLeft.GetValue()) != low.GenerateHashString(expRight.GetValue()) {
CreateChange(&changes, Modified, v3.ExampleLabel,

View File

@@ -11,6 +11,7 @@ import (
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
"github.com/pb33f/libopenapi/orderedmap"
"gopkg.in/yaml.v3"
)
// PathsChanges represents changes found between two Swagger or OpenAPI Paths Objects.
@@ -57,7 +58,6 @@ func (p *PathsChanges) TotalBreakingChanges() int {
// ComparePaths compares a left and right Swagger or OpenAPI Paths Object for changes. If found, returns a pointer
// to a PathsChanges instance. Returns nil if nothing is found.
func ComparePaths(l, r any) *PathsChanges {
var changes []*Change
pc := new(PathsChanges)
@@ -206,7 +206,7 @@ func ComparePaths(l, r any) *PathsChanges {
pc.PathItemsChanges = pathChanges
}
var lExt, rExt map[low.KeyReference[string]]low.ValueReference[any]
var lExt, rExt *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
if lPath != nil {
lExt = lPath.Extensions
}

View File

@@ -142,6 +142,10 @@ func (s *SchemaChanges) GetAllChanges() []*Change {
// TotalChanges returns a count of the total number of changes made to this schema and all sub-schemas
func (s *SchemaChanges) TotalChanges() int {
if s == nil {
return 0
}
t := s.PropertyChanges.TotalChanges()
if s.DiscriminatorChanges != nil {
t += s.DiscriminatorChanges.TotalChanges()
@@ -224,6 +228,10 @@ func (s *SchemaChanges) TotalChanges() int {
// TotalBreakingChanges returns the total number of breaking changes made to this schema and all sub-schemas.
func (s *SchemaChanges) TotalBreakingChanges() int {
if s == nil {
return 0
}
t := s.PropertyChanges.TotalBreakingChanges()
if s.DiscriminatorChanges != nil {
t += s.DiscriminatorChanges.TotalBreakingChanges()
@@ -322,33 +330,33 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
if l != nil && r != nil {
// if left proxy is a reference and right is a reference (we won't recurse into them)
if l.IsSchemaReference() && r.IsSchemaReference() {
if l.IsReference() && r.IsReference() {
// points to the same schema
if l.GetSchemaReference() == r.GetSchemaReference() {
if l.GetReference() == r.GetReference() {
// there is nothing to be done at this point.
return nil
} else {
// references are different, that's all we care to know.
CreateChange(&changes, Modified, v3.RefLabel,
l.GetValueNode().Content[1], r.GetValueNode().Content[1], true, l.GetSchemaReference(),
r.GetSchemaReference())
l.GetValueNode().Content[1], r.GetValueNode().Content[1], true, l.GetReference(),
r.GetReference())
sc.PropertyChanges = NewPropertyChanges(changes)
return sc
}
}
// changed from inline to ref
if !l.IsSchemaReference() && r.IsSchemaReference() {
if !l.IsReference() && r.IsReference() {
CreateChange(&changes, Modified, v3.RefLabel,
l.GetValueNode(), r.GetValueNode().Content[1], true, l, r.GetSchemaReference())
l.GetValueNode(), r.GetValueNode().Content[1], true, l, r.GetReference())
sc.PropertyChanges = NewPropertyChanges(changes)
return sc // we're done here
}
// changed from ref to inline
if l.IsSchemaReference() && !r.IsSchemaReference() {
if l.IsReference() && !r.IsReference() {
CreateChange(&changes, Modified, v3.RefLabel,
l.GetValueNode().Content[1], r.GetValueNode(), true, l.GetSchemaReference(), r)
l.GetValueNode().Content[1], r.GetValueNode(), true, l.GetReference(), r)
sc.PropertyChanges = NewPropertyChanges(changes)
return sc // done, nothing else to do.
}
@@ -435,7 +443,7 @@ func checkSchemaXML(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Chan
func checkMappedSchemaOfASchema(
lSchema,
rSchema orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]],
rSchema *orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]],
changes *[]*Change,
doneChan chan bool,
) (map[string]*SchemaChanges, int) {
@@ -909,10 +917,10 @@ func checkSchemaPropertyChanges(
j = make(map[string]int)
k = make(map[string]int)
for i := range lSchema.Enum.Value {
j[fmt.Sprint(lSchema.Enum.Value[i].Value)] = i
j[toString(lSchema.Enum.Value[i].Value)] = i
}
for i := range rSchema.Enum.Value {
k[fmt.Sprint(rSchema.Enum.Value[i].Value)] = i
k[toString(rSchema.Enum.Value[i].Value)] = i
}
for g := range k {
if _, ok := j[g]; !ok {

View File

@@ -34,7 +34,6 @@ func (s *SecurityRequirementChanges) TotalBreakingChanges() int {
// CompareSecurityRequirement compares left and right SecurityRequirement objects for changes. If anything
// is found, then a pointer to SecurityRequirementChanges is returned, otherwise nil.
func CompareSecurityRequirement(l, r *base.SecurityRequirement) *SecurityRequirementChanges {
var changes []*Change
sc := new(SecurityRequirementChanges)
@@ -57,9 +56,9 @@ func addedSecurityRequirement(vn *yaml.Node, name string, changes *[]*Change) {
}
// tricky to do this correctly, this is my solution.
func checkSecurityRequirement(lSec, rSec orderedmap.Map[low.KeyReference[string], low.ValueReference[[]low.ValueReference[string]]],
changes *[]*Change) {
func checkSecurityRequirement(lSec, rSec *orderedmap.Map[low.KeyReference[string], low.ValueReference[[]low.ValueReference[string]]],
changes *[]*Change,
) {
lKeys := make([]string, orderedmap.Len(lSec))
rKeys := make([]string, orderedmap.Len(rSec))
lValues := make(map[string]low.ValueReference[[]low.ValueReference[string]])