mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-07 12:37:48 +00:00
Schema what-changed almost complete.
Perhaps the biggest and most complex of all the models to determine what has changed.
This commit is contained in:
@@ -37,8 +37,10 @@ func (d *Discriminator) FindMappingValue(key string) *low.ValueReference[string]
|
|||||||
func (d *Discriminator) Hash() [32]byte {
|
func (d *Discriminator) Hash() [32]byte {
|
||||||
|
|
||||||
// calculate a hash from every property.
|
// calculate a hash from every property.
|
||||||
f := []string{d.PropertyName.Value}
|
var f []string
|
||||||
|
if d.PropertyName.Value != "" {
|
||||||
|
f = append(f, d.PropertyName.Value)
|
||||||
|
}
|
||||||
propertyKeys := make([]string, 0, len(d.Mapping))
|
propertyKeys := make([]string, 0, len(d.Mapping))
|
||||||
for i := range d.Mapping {
|
for i := range d.Mapping {
|
||||||
propertyKeys = append(propertyKeys, i.Value)
|
propertyKeys = append(propertyKeys, i.Value)
|
||||||
|
|||||||
@@ -258,6 +258,11 @@ func (s *Schema) Hash() [32]byte {
|
|||||||
d = append(d, fmt.Sprintf(x, itemsEntities[itemsKeys[k]].Hash()))
|
d = append(d, fmt.Sprintf(x, itemsEntities[itemsKeys[k]].Hash()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// add extensions to hash
|
||||||
|
for k := range s.Extensions {
|
||||||
|
d = append(d, fmt.Sprintf("%v-%x", k.Value, s.Extensions[k].Value))
|
||||||
|
}
|
||||||
|
|
||||||
return sha256.Sum256([]byte(strings.Join(d, "|")))
|
return sha256.Sum256([]byte(strings.Join(d, "|")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +305,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
s.extractExtensions(root)
|
s.extractExtensions(root)
|
||||||
|
|
||||||
// determine schema type, singular (3.0) or multiple (3.1), use a variable value
|
// determine schema type, singular (3.0) or multiple (3.1), use a variable value
|
||||||
_, typeLabel, typeValue := utils.FindKeyNodeFull(TypeLabel, root.Content)
|
_, typeLabel, typeValue := utils.FindKeyNodeFullTop(TypeLabel, root.Content)
|
||||||
if typeValue != nil {
|
if typeValue != nil {
|
||||||
if utils.IsNodeStringValue(typeValue) {
|
if utils.IsNodeStringValue(typeValue) {
|
||||||
s.Type = low.NodeReference[SchemaDynamicValue[string, []low.ValueReference[string]]]{
|
s.Type = low.NodeReference[SchemaDynamicValue[string, []low.ValueReference[string]]]{
|
||||||
@@ -327,7 +332,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// determine exclusive minimum type, bool (3.0) or int (3.1)
|
// determine exclusive minimum type, bool (3.0) or int (3.1)
|
||||||
_, exMinLabel, exMinValue := utils.FindKeyNodeFull(ExclusiveMinimumLabel, root.Content)
|
_, exMinLabel, exMinValue := utils.FindKeyNodeFullTop(ExclusiveMinimumLabel, root.Content)
|
||||||
if exMinValue != nil {
|
if exMinValue != nil {
|
||||||
if utils.IsNodeBoolValue(exMinValue) {
|
if utils.IsNodeBoolValue(exMinValue) {
|
||||||
val, _ := strconv.ParseBool(exMinValue.Value)
|
val, _ := strconv.ParseBool(exMinValue.Value)
|
||||||
@@ -348,7 +353,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// determine exclusive maximum type, bool (3.0) or int (3.1)
|
// determine exclusive maximum type, bool (3.0) or int (3.1)
|
||||||
_, exMaxLabel, exMaxValue := utils.FindKeyNodeFull(ExclusiveMaximumLabel, root.Content)
|
_, exMaxLabel, exMaxValue := utils.FindKeyNodeFullTop(ExclusiveMaximumLabel, root.Content)
|
||||||
if exMaxValue != nil {
|
if exMaxValue != nil {
|
||||||
if utils.IsNodeBoolValue(exMaxValue) {
|
if utils.IsNodeBoolValue(exMaxValue) {
|
||||||
val, _ := strconv.ParseBool(exMaxValue.Value)
|
val, _ := strconv.ParseBool(exMaxValue.Value)
|
||||||
@@ -369,7 +374,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle schema reference type if set. (3.1)
|
// handle schema reference type if set. (3.1)
|
||||||
_, schemaRefLabel, schemaRefNode := utils.FindKeyNodeFull(SchemaTypeLabel, root.Content)
|
_, schemaRefLabel, schemaRefNode := utils.FindKeyNodeFullTop(SchemaTypeLabel, root.Content)
|
||||||
if schemaRefNode != nil {
|
if schemaRefNode != nil {
|
||||||
s.SchemaTypeRef = low.NodeReference[string]{
|
s.SchemaTypeRef = low.NodeReference[string]{
|
||||||
Value: schemaRefNode.Value, KeyNode: schemaRefLabel, ValueNode: schemaRefLabel}
|
Value: schemaRefNode.Value, KeyNode: schemaRefLabel, ValueNode: schemaRefLabel}
|
||||||
@@ -382,7 +387,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle examples if set.(3.1)
|
// handle examples if set.(3.1)
|
||||||
_, expArrLabel, expArrNode := utils.FindKeyNodeFull(ExamplesLabel, root.Content)
|
_, expArrLabel, expArrNode := utils.FindKeyNodeFullTop(ExamplesLabel, root.Content)
|
||||||
if expArrNode != nil {
|
if expArrNode != nil {
|
||||||
if utils.IsNodeArray(expArrNode) {
|
if utils.IsNodeArray(expArrNode) {
|
||||||
var examples []low.ValueReference[any]
|
var examples []low.ValueReference[any]
|
||||||
@@ -397,7 +402,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, addPLabel, addPNode := utils.FindKeyNodeFull(AdditionalPropertiesLabel, root.Content)
|
_, addPLabel, addPNode := utils.FindKeyNodeFullTop(AdditionalPropertiesLabel, root.Content)
|
||||||
if addPNode != nil {
|
if addPNode != nil {
|
||||||
if utils.IsNodeMap(addPNode) {
|
if utils.IsNodeMap(addPNode) {
|
||||||
schema, serr := low.ExtractObjectRaw[*Schema](addPNode, idx)
|
schema, serr := low.ExtractObjectRaw[*Schema](addPNode, idx)
|
||||||
@@ -414,7 +419,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle discriminator if set.
|
// handle discriminator if set.
|
||||||
_, discLabel, discNode := utils.FindKeyNodeFull(DiscriminatorLabel, root.Content)
|
_, discLabel, discNode := utils.FindKeyNodeFullTop(DiscriminatorLabel, root.Content)
|
||||||
if discNode != nil {
|
if discNode != nil {
|
||||||
var discriminator Discriminator
|
var discriminator Discriminator
|
||||||
_ = low.BuildModel(discNode, &discriminator)
|
_ = low.BuildModel(discNode, &discriminator)
|
||||||
@@ -422,7 +427,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle externalDocs if set.
|
// handle externalDocs if set.
|
||||||
_, extDocLabel, extDocNode := utils.FindKeyNodeFull(ExternalDocsLabel, root.Content)
|
_, extDocLabel, extDocNode := utils.FindKeyNodeFullTop(ExternalDocsLabel, root.Content)
|
||||||
if extDocNode != nil {
|
if extDocNode != nil {
|
||||||
var exDoc ExternalDoc
|
var exDoc ExternalDoc
|
||||||
_ = low.BuildModel(extDocNode, &exDoc)
|
_ = low.BuildModel(extDocNode, &exDoc)
|
||||||
@@ -431,7 +436,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle xml if set.
|
// handle xml if set.
|
||||||
_, xmlLabel, xmlNode := utils.FindKeyNodeFull(XMLLabel, root.Content)
|
_, xmlLabel, xmlNode := utils.FindKeyNodeFullTop(XMLLabel, root.Content)
|
||||||
if xmlNode != nil {
|
if xmlNode != nil {
|
||||||
var xml XML
|
var xml XML
|
||||||
_ = low.BuildModel(xmlNode, &xml)
|
_ = low.BuildModel(xmlNode, &xml)
|
||||||
@@ -457,7 +462,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle properties
|
// handle properties
|
||||||
_, propLabel, propsNode := utils.FindKeyNodeFull(PropertiesLabel, root.Content)
|
_, propLabel, propsNode := utils.FindKeyNodeFullTop(PropertiesLabel, root.Content)
|
||||||
if propsNode != nil {
|
if propsNode != nil {
|
||||||
propertyMap := make(map[low.KeyReference[string]]low.ValueReference[*SchemaProxy])
|
propertyMap := make(map[low.KeyReference[string]]low.ValueReference[*SchemaProxy])
|
||||||
var currentProp *yaml.Node
|
var currentProp *yaml.Node
|
||||||
@@ -498,11 +503,11 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
|
|
||||||
var allOf, anyOf, oneOf, not, items []low.ValueReference[*SchemaProxy]
|
var allOf, anyOf, oneOf, not, items []low.ValueReference[*SchemaProxy]
|
||||||
|
|
||||||
_, allOfLabel, allOfValue := utils.FindKeyNodeFull(AllOfLabel, root.Content)
|
_, allOfLabel, allOfValue := utils.FindKeyNodeFullTop(AllOfLabel, root.Content)
|
||||||
_, anyOfLabel, anyOfValue := utils.FindKeyNodeFull(AnyOfLabel, root.Content)
|
_, anyOfLabel, anyOfValue := utils.FindKeyNodeFullTop(AnyOfLabel, root.Content)
|
||||||
_, oneOfLabel, oneOfValue := utils.FindKeyNodeFull(OneOfLabel, root.Content)
|
_, oneOfLabel, oneOfValue := utils.FindKeyNodeFullTop(OneOfLabel, root.Content)
|
||||||
_, notLabel, notValue := utils.FindKeyNodeFull(NotLabel, root.Content)
|
_, notLabel, notValue := utils.FindKeyNodeFullTop(NotLabel, root.Content)
|
||||||
_, itemsLabel, itemsValue := utils.FindKeyNodeFull(ItemsLabel, root.Content)
|
_, itemsLabel, itemsValue := utils.FindKeyNodeFullTop(ItemsLabel, root.Content)
|
||||||
|
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
allOfChan := make(chan schemaProxyBuildResult)
|
allOfChan := make(chan schemaProxyBuildResult)
|
||||||
|
|||||||
@@ -198,3 +198,7 @@ func GetCircularReferenceResult(node *yaml.Node, idx *index.SpecIndex) *index.Ci
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HashToString(hash [32]byte) string {
|
||||||
|
return fmt.Sprintf("%x", hash)
|
||||||
|
}
|
||||||
|
|||||||
@@ -90,4 +90,6 @@ const (
|
|||||||
DeprecatedLabel = "deprecated"
|
DeprecatedLabel = "deprecated"
|
||||||
ExampleLabel = "example"
|
ExampleLabel = "example"
|
||||||
RefLabel = "$ref"
|
RefLabel = "$ref"
|
||||||
|
DiscriminatorLabel = "discriminator"
|
||||||
|
ExternalDocsLabel = "externalDocs"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ func FindKeyNode(key string, nodes []*yaml.Node) (keyNode *yaml.Node, valueNode
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindKeyNodeFull is an overloaded version of FindKeyNode. Thins version however returns keys, labels and values.
|
// FindKeyNodeFull is an overloaded version of FindKeyNode. This version however returns keys, labels and values.
|
||||||
// generally different things are required from different node trees, so depending on what this function is looking at
|
// generally different things are required from different node trees, so depending on what this function is looking at
|
||||||
// it will return different things.
|
// it will return different things.
|
||||||
func FindKeyNodeFull(key string, nodes []*yaml.Node) (keyNode *yaml.Node, labelNode *yaml.Node, valueNode *yaml.Node) {
|
func FindKeyNodeFull(key string, nodes []*yaml.Node) (keyNode *yaml.Node, labelNode *yaml.Node, valueNode *yaml.Node) {
|
||||||
@@ -267,6 +267,33 @@ func FindKeyNodeFull(key string, nodes []*yaml.Node) (keyNode *yaml.Node, labelN
|
|||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindKeyNodeFullTop is an overloaded version of FindKeyNodeFull. This version only looks at the top
|
||||||
|
// level of the node and not the children.
|
||||||
|
func FindKeyNodeFullTop(key string, nodes []*yaml.Node) (keyNode *yaml.Node, labelNode *yaml.Node, valueNode *yaml.Node) {
|
||||||
|
for i := range nodes {
|
||||||
|
if i%2 == 0 && key == nodes[i].Value {
|
||||||
|
return nodes[i], nodes[i], nodes[i+1] // next node is what we need.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for q, v := range nodes {
|
||||||
|
if q%2 != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if key == v.Value {
|
||||||
|
if IsNodeMap(v) {
|
||||||
|
if q+1 == len(v.Content) {
|
||||||
|
return v, v.Content[q], v.Content[q]
|
||||||
|
}
|
||||||
|
return v, v.Content[q], v.Content[q+1]
|
||||||
|
}
|
||||||
|
if IsNodeArray(v) {
|
||||||
|
return v, v.Content[q], v.Content[q]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
type ExtensionNode struct {
|
type ExtensionNode struct {
|
||||||
Key *yaml.Node
|
Key *yaml.Node
|
||||||
Value *yaml.Node
|
Value *yaml.Node
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@@ -109,12 +110,6 @@ func (s *SchemaChanges) TotalBreakingChanges() int {
|
|||||||
t += s.SchemaPropertyChanges[n].TotalBreakingChanges()
|
t += s.SchemaPropertyChanges[n].TotalBreakingChanges()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.ExternalDocChanges != nil {
|
|
||||||
t += s.ExternalDocChanges.TotalBreakingChanges()
|
|
||||||
}
|
|
||||||
if s.ExtensionChanges != nil {
|
|
||||||
t += s.ExtensionChanges.TotalBreakingChanges()
|
|
||||||
}
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,26 +520,69 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Discriminator
|
||||||
|
if lSchema.Discriminator.Value != nil && rSchema.Discriminator.Value != nil {
|
||||||
|
// check if hash matches, if not then compare.
|
||||||
|
if lSchema.Discriminator.Value.Hash() != rSchema.Discriminator.Value.Hash() {
|
||||||
|
sc.DiscriminatorChanges = CompareDiscriminator(lSchema.Discriminator.Value, rSchema.Discriminator.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// added Discriminator
|
||||||
|
if lSchema.Discriminator.Value == nil && rSchema.Discriminator.Value != nil {
|
||||||
|
CreateChange[*base.Schema](&changes, ObjectAdded, v3.DiscriminatorLabel,
|
||||||
|
nil, rSchema.Discriminator.ValueNode, true, nil, rSchema.Discriminator.Value)
|
||||||
|
}
|
||||||
|
// removed Discriminator
|
||||||
|
if lSchema.Discriminator.Value != nil && rSchema.Discriminator.Value == nil {
|
||||||
|
CreateChange[*base.Schema](&changes, ObjectRemoved, v3.DiscriminatorLabel,
|
||||||
|
lSchema.Discriminator.ValueNode, nil, true, lSchema.Discriminator.Value, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExternalDocs
|
||||||
|
if lSchema.ExternalDocs.Value != nil && rSchema.ExternalDocs.Value != nil {
|
||||||
|
// check if hash matches, if not then compare.
|
||||||
|
if lSchema.ExternalDocs.Value.Hash() != rSchema.ExternalDocs.Value.Hash() {
|
||||||
|
sc.ExternalDocChanges = CompareExternalDocs(lSchema.ExternalDocs.Value, rSchema.ExternalDocs.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// added ExternalDocs
|
||||||
|
if lSchema.ExternalDocs.Value == nil && rSchema.ExternalDocs.Value != nil {
|
||||||
|
CreateChange[*base.Schema](&changes, ObjectAdded, v3.ExternalDocsLabel,
|
||||||
|
nil, rSchema.ExternalDocs.ValueNode, false, nil, rSchema.ExternalDocs.Value)
|
||||||
|
}
|
||||||
|
// removed ExternalDocs
|
||||||
|
if lSchema.ExternalDocs.Value != nil && rSchema.ExternalDocs.Value == nil {
|
||||||
|
CreateChange[*base.Schema](&changes, ObjectRemoved, v3.ExternalDocsLabel,
|
||||||
|
lSchema.ExternalDocs.ValueNode, nil, false, lSchema.ExternalDocs.Value, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check extensions
|
||||||
|
sc.ExtensionChanges = CompareExtensions(lSchema.Extensions, rSchema.Extensions)
|
||||||
|
|
||||||
// check core properties
|
// check core properties
|
||||||
CheckProperties(props)
|
CheckProperties(props)
|
||||||
|
|
||||||
propChanges := make(map[string]*SchemaChanges)
|
propChanges := make(map[string]*SchemaChanges)
|
||||||
|
|
||||||
lProps := make([]string, len(lSchema.Properties.Value))
|
var lProps []string
|
||||||
lEntities := make(map[string]*base.SchemaProxy)
|
lEntities := make(map[string]*base.SchemaProxy)
|
||||||
rProps := make([]string, len(rSchema.Properties.Value))
|
lKeyNodes := make(map[string]*yaml.Node)
|
||||||
|
var rProps []string
|
||||||
rEntities := make(map[string]*base.SchemaProxy)
|
rEntities := make(map[string]*base.SchemaProxy)
|
||||||
|
rKeyNodes := make(map[string]*yaml.Node)
|
||||||
|
|
||||||
for w := range lSchema.Properties.Value {
|
for w := range lSchema.Properties.Value {
|
||||||
if !lSchema.Properties.Value[w].Value.IsSchemaReference() {
|
if !lSchema.Properties.Value[w].Value.IsSchemaReference() {
|
||||||
lProps = append(lProps, w.Value)
|
lProps = append(lProps, w.Value)
|
||||||
lEntities[w.Value] = lSchema.Properties.Value[w].Value
|
lEntities[w.Value] = lSchema.Properties.Value[w].Value
|
||||||
|
lKeyNodes[w.Value] = w.KeyNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for w := range rSchema.Properties.Value {
|
for w := range rSchema.Properties.Value {
|
||||||
if !rSchema.Properties.Value[w].Value.IsSchemaReference() {
|
if !rSchema.Properties.Value[w].Value.IsSchemaReference() {
|
||||||
rProps = append(rProps, w.Value)
|
rProps = append(rProps, w.Value)
|
||||||
rEntities[w.Value] = rSchema.Properties.Value[w].Value
|
rEntities[w.Value] = rSchema.Properties.Value[w].Value
|
||||||
|
rKeyNodes[w.Value] = w.KeyNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort.Strings(lProps)
|
sort.Strings(lProps)
|
||||||
@@ -583,9 +621,10 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
|||||||
|
|
||||||
// old removed, new added.
|
// old removed, new added.
|
||||||
CreateChange[*base.Schema](&changes, ObjectAdded, v3.PropertiesLabel,
|
CreateChange[*base.Schema](&changes, ObjectAdded, v3.PropertiesLabel,
|
||||||
nil, rEntities[rProps[w]].GetValueNode(), false, nil, rEntities[rProps[w]])
|
nil, rKeyNodes[rProps[w]], false, nil, rEntities[rProps[w]])
|
||||||
|
|
||||||
CreateChange[*base.Schema](&changes, ObjectRemoved, v3.PropertiesLabel,
|
CreateChange[*base.Schema](&changes, ObjectRemoved, v3.PropertiesLabel,
|
||||||
lEntities[lProps[w]].GetValueNode(), nil, true, lEntities[lProps[w]], nil)
|
lKeyNodes[lProps[w]], nil, true, lEntities[lProps[w]], nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -600,7 +639,7 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
|||||||
}
|
}
|
||||||
if w >= len(rProps) {
|
if w >= len(rProps) {
|
||||||
CreateChange[*base.Schema](&changes, ObjectRemoved, v3.PropertiesLabel,
|
CreateChange[*base.Schema](&changes, ObjectRemoved, v3.PropertiesLabel,
|
||||||
lEntities[lProps[w]].GetValueNode(), nil, true, lEntities[lProps[w]], nil)
|
lKeyNodes[lProps[w]], nil, true, lEntities[lProps[w]], nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -612,9 +651,9 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
|||||||
totalProperties++
|
totalProperties++
|
||||||
go checkProperty(rProps[w], lEntities[lProps[w]], rEntities[rProps[w]], propChanges, doneChan)
|
go checkProperty(rProps[w], lEntities[lProps[w]], rEntities[rProps[w]], propChanges, doneChan)
|
||||||
}
|
}
|
||||||
if w >= len(rProps) {
|
if w >= len(lProps) {
|
||||||
CreateChange[*base.Schema](&changes, ObjectAdded, v3.PropertiesLabel,
|
CreateChange[*base.Schema](&changes, ObjectAdded, v3.PropertiesLabel,
|
||||||
nil, rEntities[rProps[w]].GetValueNode(), false, nil, rEntities[rProps[w]])
|
nil, rKeyNodes[rProps[w]], false, nil, rEntities[rProps[w]])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -634,8 +673,8 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
|||||||
go extractSchemaChanges(lSchema.Items.Value, rSchema.Items.Value, v3.ItemsLabel,
|
go extractSchemaChanges(lSchema.Items.Value, rSchema.Items.Value, v3.ItemsLabel,
|
||||||
&sc.ItemsChanges, &changes, doneChan)
|
&sc.ItemsChanges, &changes, doneChan)
|
||||||
|
|
||||||
go extractSchemaChanges(lSchema.Not.Value, rSchema.Not.Value, v3.ItemsLabel,
|
go extractSchemaChanges(lSchema.Not.Value, rSchema.Not.Value, v3.NotLabel,
|
||||||
&sc.ItemsChanges, &changes, doneChan)
|
&sc.NotChanges, &changes, doneChan)
|
||||||
|
|
||||||
totalChecks := totalProperties + 5
|
totalChecks := totalProperties + 5
|
||||||
completedChecks := 0
|
completedChecks := 0
|
||||||
@@ -645,16 +684,12 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
|||||||
completedChecks++
|
completedChecks++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// done
|
// done
|
||||||
sc.Changes = changes
|
if changes != nil {
|
||||||
if sc.TotalChanges() <= 0 {
|
sc.Changes = changes
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return sc
|
return sc
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractSchemaChanges(
|
func extractSchemaChanges(
|
||||||
@@ -696,11 +731,6 @@ func extractSchemaChanges(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(lKeys) <= 0 && len(rKeys) <= 0 {
|
|
||||||
done <- true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort slices so that like for like is all sequenced.
|
// sort slices so that like for like is all sequenced.
|
||||||
sort.Strings(lKeys)
|
sort.Strings(lKeys)
|
||||||
sort.Strings(rKeys)
|
sort.Strings(rKeys)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package what_changed
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -286,3 +287,693 @@ func TestCompareSchemas_Identical(t *testing.T) {
|
|||||||
changes := CompareSchemas(rSchemaProxy, lSchemaProxy)
|
changes := CompareSchemas(rSchemaProxy, lSchemaProxy)
|
||||||
assert.Nil(t, changes)
|
assert.Nil(t, changes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_RequiredAdded(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
title: an OK message
|
||||||
|
description: a thing
|
||||||
|
required:
|
||||||
|
- one`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
title: an OK message
|
||||||
|
description: a thing
|
||||||
|
required:
|
||||||
|
- one
|
||||||
|
- two`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Len(t, changes.Changes, 1)
|
||||||
|
assert.Equal(t, PropertyAdded, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "two", changes.Changes[0].New)
|
||||||
|
assert.Equal(t, v3.RequiredLabel, changes.Changes[0].Property)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_RequiredRemoved(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
required:
|
||||||
|
- one`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
required:
|
||||||
|
- one
|
||||||
|
- two`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(rSchemaProxy, lSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Len(t, changes.Changes, 1)
|
||||||
|
assert.Equal(t, PropertyRemoved, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "two", changes.Changes[0].Original)
|
||||||
|
assert.Equal(t, v3.RequiredLabel, changes.Changes[0].Property)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_EnumAdded(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
enum: [a,b,c]`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
enum: [a,b,c,d]`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Len(t, changes.Changes, 1)
|
||||||
|
assert.Equal(t, PropertyAdded, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "d", changes.Changes[0].New)
|
||||||
|
assert.Equal(t, v3.EnumLabel, changes.Changes[0].Property)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_EnumRemoved(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
enum: [a,b,c]`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
enum: [a,b,c,d]`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(rSchemaProxy, lSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Len(t, changes.Changes, 1)
|
||||||
|
assert.Equal(t, PropertyRemoved, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "d", changes.Changes[0].Original)
|
||||||
|
assert.Equal(t, v3.EnumLabel, changes.Changes[0].Property)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_PropertyAdded(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
properties:
|
||||||
|
propA:
|
||||||
|
type: int`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
properties:
|
||||||
|
propB:
|
||||||
|
type: string
|
||||||
|
propA:
|
||||||
|
type: int`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Len(t, changes.Changes, 1)
|
||||||
|
assert.Equal(t, ObjectAdded, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "propB", changes.Changes[0].New)
|
||||||
|
assert.Equal(t, v3.PropertiesLabel, changes.Changes[0].Property)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_PropertyRemoved(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
properties:
|
||||||
|
propA:
|
||||||
|
type: int`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
properties:
|
||||||
|
propB:
|
||||||
|
type: string
|
||||||
|
propA:
|
||||||
|
type: int`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(rSchemaProxy, lSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Len(t, changes.Changes, 1)
|
||||||
|
assert.Equal(t, ObjectRemoved, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "propB", changes.Changes[0].Original)
|
||||||
|
assert.Equal(t, v3.PropertiesLabel, changes.Changes[0].Property)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_PropertyChanged(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
properties:
|
||||||
|
propA:
|
||||||
|
type: int`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
properties:
|
||||||
|
propA:
|
||||||
|
type: string`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, Modified, changes.SchemaPropertyChanges["propA"].Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "string", changes.SchemaPropertyChanges["propA"].Changes[0].New)
|
||||||
|
assert.Equal(t, "int", changes.SchemaPropertyChanges["propA"].Changes[0].Original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_PropertySwap(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
properties:
|
||||||
|
propA:
|
||||||
|
type: int`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
properties:
|
||||||
|
propN:
|
||||||
|
type: string`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 2, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, ObjectAdded, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "propN", changes.Changes[0].New)
|
||||||
|
assert.Equal(t, v3.PropertiesLabel, changes.Changes[0].Property)
|
||||||
|
assert.Equal(t, ObjectRemoved, changes.Changes[1].ChangeType)
|
||||||
|
assert.Equal(t, "propA", changes.Changes[1].Original)
|
||||||
|
assert.Equal(t, v3.PropertiesLabel, changes.Changes[1].Property)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_AnyOfModifyAndAddItem(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
anyOf:
|
||||||
|
- type: bool`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: int"`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 2, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, ObjectAdded, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, v3.AnyOfLabel, changes.Changes[0].Property)
|
||||||
|
assert.Equal(t, Modified, changes.AnyOfChanges[0].Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "string", changes.AnyOfChanges[0].Changes[0].New)
|
||||||
|
assert.Equal(t, "bool", changes.AnyOfChanges[0].Changes[0].Original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_AnyOfModifyAndRemoveItem(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
anyOf:
|
||||||
|
- type: bool`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: int"`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(rSchemaProxy, lSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 2, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 2, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, ObjectRemoved, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, v3.AnyOfLabel, changes.Changes[0].Property)
|
||||||
|
assert.Equal(t, Modified, changes.AnyOfChanges[0].Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "bool", changes.AnyOfChanges[0].Changes[0].New)
|
||||||
|
assert.Equal(t, "string", changes.AnyOfChanges[0].Changes[0].Original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_AnyOfModified(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
anyOf:
|
||||||
|
- type: bool`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
anyOf:
|
||||||
|
- type: string`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, Modified, changes.AnyOfChanges[0].Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "string", changes.AnyOfChanges[0].Changes[0].New)
|
||||||
|
assert.Equal(t, "bool", changes.AnyOfChanges[0].Changes[0].Original)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_OneOfModifyAndAddItem(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
oneOf:
|
||||||
|
- type: bool`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
oneOf:
|
||||||
|
- type: string
|
||||||
|
- type: int"`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 2, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, ObjectAdded, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, v3.OneOfLabel, changes.Changes[0].Property)
|
||||||
|
assert.Equal(t, Modified, changes.OneOfChanges[0].Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "string", changes.OneOfChanges[0].Changes[0].New)
|
||||||
|
assert.Equal(t, "bool", changes.OneOfChanges[0].Changes[0].Original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_AllOfModifyAndAddItem(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
allOf:
|
||||||
|
- type: bool`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
allOf:
|
||||||
|
- type: string
|
||||||
|
- type: int"`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 2, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, ObjectAdded, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, v3.AllOfLabel, changes.Changes[0].Property)
|
||||||
|
assert.Equal(t, Modified, changes.AllOfChanges[0].Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "string", changes.AllOfChanges[0].Changes[0].New)
|
||||||
|
assert.Equal(t, "bool", changes.AllOfChanges[0].Changes[0].Original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_ItemsModifyAndAddItem(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
items:
|
||||||
|
type: bool`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
items:
|
||||||
|
type: string`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, v3.TypeLabel, changes.ItemsChanges[0].Changes[0].Property)
|
||||||
|
assert.Equal(t, Modified, changes.ItemsChanges[0].Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "string", changes.ItemsChanges[0].Changes[0].New)
|
||||||
|
assert.Equal(t, "bool", changes.ItemsChanges[0].Changes[0].Original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_ItemsModifyAndAddItemArray(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
items:
|
||||||
|
- type: bool`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
items:
|
||||||
|
- type: string`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, v3.TypeLabel, changes.ItemsChanges[0].Changes[0].Property)
|
||||||
|
assert.Equal(t, Modified, changes.ItemsChanges[0].Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "string", changes.ItemsChanges[0].Changes[0].New)
|
||||||
|
assert.Equal(t, "bool", changes.ItemsChanges[0].Changes[0].Original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_NotModifyAndAddItem(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
not:
|
||||||
|
type: bool`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
not:
|
||||||
|
type: string`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, v3.TypeLabel, changes.NotChanges[0].Changes[0].Property)
|
||||||
|
assert.Equal(t, Modified, changes.NotChanges[0].Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "string", changes.NotChanges[0].Changes[0].New)
|
||||||
|
assert.Equal(t, "bool", changes.NotChanges[0].Changes[0].Original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_DiscriminatorChange(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
discriminator:
|
||||||
|
propertyName: melody`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
discriminator:
|
||||||
|
propertyName: maddox`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, v3.PropertyNameLabel, changes.DiscriminatorChanges.Changes[0].Property)
|
||||||
|
assert.Equal(t, Modified, changes.DiscriminatorChanges.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "maddox", changes.DiscriminatorChanges.Changes[0].New)
|
||||||
|
assert.Equal(t, "melody", changes.DiscriminatorChanges.Changes[0].Original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_DiscriminatorAdd(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
discriminator:
|
||||||
|
propertyName: maddox`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, v3.DiscriminatorLabel, changes.Changes[0].Property)
|
||||||
|
assert.Equal(t, ObjectAdded, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "0e563831440581c713657dd857a0ec3af1bd7308a43bd3cae9184f61d61b288f",
|
||||||
|
low.HashToString(changes.Changes[0].NewObject.(*base.Discriminator).Hash()))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_DiscriminatorRemove(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
discriminator:
|
||||||
|
propertyName: maddox`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(rSchemaProxy, lSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 1, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, v3.DiscriminatorLabel, changes.Changes[0].Property)
|
||||||
|
assert.Equal(t, ObjectRemoved, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "0e563831440581c713657dd857a0ec3af1bd7308a43bd3cae9184f61d61b288f",
|
||||||
|
low.HashToString(changes.Changes[0].OriginalObject.(*base.Discriminator).Hash()))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_ExternalDocsChange(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
externalDocs:
|
||||||
|
url: https://pb33f.io`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
externalDocs:
|
||||||
|
url: https://pb33f.io/new`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 0, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, v3.URLLabel, changes.ExternalDocChanges.Changes[0].Property)
|
||||||
|
assert.Equal(t, Modified, changes.ExternalDocChanges.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "https://pb33f.io/new", changes.ExternalDocChanges.Changes[0].New)
|
||||||
|
assert.Equal(t, "https://pb33f.io", changes.ExternalDocChanges.Changes[0].Original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_ExternalDocsAdd(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
externalDocs:
|
||||||
|
url: https://pb33f.io`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 0, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, v3.ExternalDocsLabel, changes.Changes[0].Property)
|
||||||
|
assert.Equal(t, ObjectAdded, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "2b7adf30f2ea3a7617ccf429a099617a9c03e8b5f3a23a89dba4b90f760010d7",
|
||||||
|
low.HashToString(changes.Changes[0].NewObject.(*base.ExternalDoc).Hash()))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_ExternalDocsRemove(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
externalDocs:
|
||||||
|
url: https://pb33f.io`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(rSchemaProxy, lSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 0, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, v3.ExternalDocsLabel, changes.Changes[0].Property)
|
||||||
|
assert.Equal(t, ObjectRemoved, changes.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "2b7adf30f2ea3a7617ccf429a099617a9c03e8b5f3a23a89dba4b90f760010d7",
|
||||||
|
low.HashToString(changes.Changes[0].OriginalObject.(*base.ExternalDoc).Hash()))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareSchemas_AddExtension(t *testing.T) {
|
||||||
|
left := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string`
|
||||||
|
|
||||||
|
right := `components:
|
||||||
|
schemas:
|
||||||
|
OK:
|
||||||
|
type: string
|
||||||
|
x-melody: song`
|
||||||
|
|
||||||
|
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||||
|
|
||||||
|
// extract left reference schema and non reference schema.
|
||||||
|
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||||
|
|
||||||
|
changes := CompareSchemas(lSchemaProxy, rSchemaProxy)
|
||||||
|
assert.NotNil(t, changes)
|
||||||
|
assert.Equal(t, 1, changes.TotalChanges())
|
||||||
|
assert.Equal(t, 0, changes.TotalBreakingChanges())
|
||||||
|
assert.Equal(t, "x-melody", changes.ExtensionChanges.Changes[0].Property)
|
||||||
|
assert.Equal(t, ObjectAdded, changes.ExtensionChanges.Changes[0].ChangeType)
|
||||||
|
assert.Equal(t, "song", changes.ExtensionChanges.Changes[0].New)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user