From a184c5e909c83a830d9bb30abdc1aa393168de9e Mon Sep 17 00:00:00 2001 From: Dave Shanley Date: Fri, 4 Nov 2022 09:50:20 -0400 Subject: [PATCH] Fixed a low level bug with locating nodes. locating nodes was looking through two levels to locate something. This is not the correct behavior, after making the change - lots of tests needed to be updated to be correct in what they put into as a the root node. --- datamodel/high/base/contact_test.go | 4 +- datamodel/high/base/discriminator_test.go | 60 +++++++++---------- datamodel/high/base/example_test.go | 8 +-- datamodel/high/base/external_doc_test.go | 4 +- datamodel/high/base/info_test.go | 4 +- datamodel/high/base/tag_test.go | 68 +++++++++++----------- datamodel/high/base/xml_test.go | 38 ++++++------ datamodel/high/v3/response_test.go | 2 +- datamodel/low/base/discriminator_test.go | 2 +- datamodel/low/base/example_test.go | 8 +-- datamodel/low/base/external_doc_test.go | 2 +- datamodel/low/base/info_test.go | 2 +- datamodel/low/base/schema_proxy_test.go | 2 +- datamodel/low/base/schema_test.go | 4 +- datamodel/low/base/tag_test.go | 2 +- datamodel/low/extraction_functions_test.go | 5 +- datamodel/low/model_builder.go | 2 +- datamodel/low/model_builder_test.go | 18 +++--- datamodel/low/v2/paths.go | 35 +++++++++++ datamodel/low/v2/swagger.go | 4 +- datamodel/low/v2/swagger_test.go | 1 + datamodel/low/v3/components_test.go | 6 +- datamodel/low/v3/constants.go | 1 + datamodel/low/v3/encoding_test.go | 2 +- datamodel/low/v3/header_test.go | 2 +- datamodel/low/v3/link_test.go | 2 +- datamodel/low/v3/oauth_flows_test.go | 2 +- datamodel/low/v3/operation_test.go | 2 +- datamodel/low/v3/parameter_test.go | 2 +- datamodel/low/v3/paths.go | 24 ++++++++ datamodel/low/v3/request_body_test.go | 4 +- datamodel/low/v3/security_scheme_test.go | 2 +- datamodel/low/v3/server_test.go | 4 +- what-changed/model/path_item.go | 53 +++++++++-------- 34 files changed, 220 insertions(+), 161 deletions(-) diff --git a/datamodel/high/base/contact_test.go b/datamodel/high/base/contact_test.go index 62b6362..f2469ba 100644 --- a/datamodel/high/base/contact_test.go +++ b/datamodel/high/base/contact_test.go @@ -24,7 +24,7 @@ email: buckaroo@pb33f.io` // build low var lowContact lowbase.Contact - _ = lowmodel.BuildModel(&cNode, &lowContact) + _ = lowmodel.BuildModel(cNode.Content[0], &lowContact) // build high highContact := NewContact(&lowContact) @@ -49,7 +49,7 @@ email: buckaroo@pb33f.io` // build low var lowContact lowbase.Contact - _ = lowmodel.BuildModel(&cNode, &lowContact) + _ = lowmodel.BuildModel(cNode.Content[0], &lowContact) // build high highContact := NewContact(&lowContact) diff --git a/datamodel/high/base/discriminator_test.go b/datamodel/high/base/discriminator_test.go index ad1ec78..ec29a10 100644 --- a/datamodel/high/base/discriminator_test.go +++ b/datamodel/high/base/discriminator_test.go @@ -4,56 +4,56 @@ package base import ( - "fmt" - lowmodel "github.com/pb33f/libopenapi/datamodel/low" - lowbase "github.com/pb33f/libopenapi/datamodel/low/base" - "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v3" - "testing" + "fmt" + lowmodel "github.com/pb33f/libopenapi/datamodel/low" + lowbase "github.com/pb33f/libopenapi/datamodel/low/base" + "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v3" + "testing" ) func TestNewDiscriminator(t *testing.T) { - var cNode yaml.Node + var cNode yaml.Node - yml := `propertyName: coffee + yml := `propertyName: coffee mapping: fogCleaner: in the morning` - _ = yaml.Unmarshal([]byte(yml), &cNode) + _ = yaml.Unmarshal([]byte(yml), &cNode) - // build low - var lowDiscriminator lowbase.Discriminator - _ = lowmodel.BuildModel(&cNode, &lowDiscriminator) + // build low + var lowDiscriminator lowbase.Discriminator + _ = lowmodel.BuildModel(cNode.Content[0], &lowDiscriminator) - // build high - highDiscriminator := NewDiscriminator(&lowDiscriminator) + // build high + highDiscriminator := NewDiscriminator(&lowDiscriminator) - assert.Equal(t, "coffee", highDiscriminator.PropertyName) - assert.Equal(t, "in the morning", highDiscriminator.Mapping["fogCleaner"]) - assert.Equal(t, 3, highDiscriminator.GoLow().FindMappingValue("fogCleaner").ValueNode.Line) + assert.Equal(t, "coffee", highDiscriminator.PropertyName) + assert.Equal(t, "in the morning", highDiscriminator.Mapping["fogCleaner"]) + assert.Equal(t, 3, highDiscriminator.GoLow().FindMappingValue("fogCleaner").ValueNode.Line) } func ExampleNewDiscriminator() { - // create a yaml representation of a discriminator (can be JSON, doesn't matter) - yml := `propertyName: coffee + // create a yaml representation of a discriminator (can be JSON, doesn't matter) + yml := `propertyName: coffee mapping: coffee: in the morning` - // unmarshal into a *yaml.Node - var node yaml.Node - _ = yaml.Unmarshal([]byte(yml), &node) + // unmarshal into a *yaml.Node + var node yaml.Node + _ = yaml.Unmarshal([]byte(yml), &node) - // build low-level model - var lowDiscriminator lowbase.Discriminator - _ = lowmodel.BuildModel(&node, &lowDiscriminator) + // build low-level model + var lowDiscriminator lowbase.Discriminator + _ = lowmodel.BuildModel(node.Content[0], &lowDiscriminator) - // build high-level model - highDiscriminator := NewDiscriminator(&lowDiscriminator) + // build high-level model + highDiscriminator := NewDiscriminator(&lowDiscriminator) - // print out a mapping defined for the discriminator. - fmt.Print(highDiscriminator.Mapping["coffee"]) - // Output: in the morning + // print out a mapping defined for the discriminator. + fmt.Print(highDiscriminator.Mapping["coffee"]) + // Output: in the morning } diff --git a/datamodel/high/base/example_test.go b/datamodel/high/base/example_test.go index c9a4105..0c32518 100644 --- a/datamodel/high/base/example_test.go +++ b/datamodel/high/base/example_test.go @@ -26,7 +26,7 @@ x-hack: code` // build low var lowExample lowbase.Example - _ = lowmodel.BuildModel(&cNode, &lowExample) + _ = lowmodel.BuildModel(cNode.Content[0], &lowExample) _ = lowExample.Build(cNode.Content[0], nil) @@ -50,7 +50,7 @@ func TestExtractExamples(t *testing.T) { // build low var lowExample lowbase.Example - _ = lowmodel.BuildModel(&cNode, &lowExample) + _ = lowmodel.BuildModel(cNode.Content[0], &lowExample) _ = lowExample.Build(cNode.Content[0], nil) @@ -79,7 +79,7 @@ x-hack: code` // build low-level example var lowExample lowbase.Example - _ = lowmodel.BuildModel(&node, &lowExample) + _ = lowmodel.BuildModel(node.Content[0], &lowExample) // build out low-level example _ = lowExample.Build(node.Content[0], nil) @@ -90,4 +90,4 @@ x-hack: code` fmt.Print(highExample.ExternalValue) // Output: https://pb33f.io -} \ No newline at end of file +} diff --git a/datamodel/high/base/external_doc_test.go b/datamodel/high/base/external_doc_test.go index 44cdc70..5708a43 100644 --- a/datamodel/high/base/external_doc_test.go +++ b/datamodel/high/base/external_doc_test.go @@ -23,7 +23,7 @@ x-hack: code` _ = yaml.Unmarshal([]byte(yml), &cNode) var lowExt lowbase.ExternalDoc - _ = lowmodel.BuildModel(&cNode, &lowExt) + _ = lowmodel.BuildModel(cNode.Content[0], &lowExt) _ = lowExt.Build(cNode.Content[0], nil) @@ -51,7 +51,7 @@ x-hack: code` // build low-level ExternalDoc var lowExt lowbase.ExternalDoc - _ = lowmodel.BuildModel(&node, &lowExt) + _ = lowmodel.BuildModel(node.Content[0], &lowExt) // build out low-level properties (like extensions) _ = lowExt.Build(node.Content[0], nil) diff --git a/datamodel/high/base/info_test.go b/datamodel/high/base/info_test.go index 6789ef0..49f9c53 100644 --- a/datamodel/high/base/info_test.go +++ b/datamodel/high/base/info_test.go @@ -31,7 +31,7 @@ x-cli-name: chicken cli` _ = yaml.Unmarshal([]byte(yml), &cNode) var lowInfo lowbase.Info - _ = lowmodel.BuildModel(&cNode, &lowInfo) + _ = lowmodel.BuildModel(cNode.Content[0], &lowInfo) _ = lowInfo.Build(cNode.Content[0], nil) highInfo := NewInfo(&lowInfo) @@ -97,7 +97,7 @@ url: https://opensource.org/licenses/MIT` // build out the low-level model var lowLicense lowbase.License - _ = lowmodel.BuildModel(&node, &lowLicense) + _ = lowmodel.BuildModel(node.Content[0], &lowLicense) _ = lowLicense.Build(node.Content[0], nil) // build the high level model diff --git a/datamodel/high/base/tag_test.go b/datamodel/high/base/tag_test.go index 038fa18..dcecd90 100644 --- a/datamodel/high/base/tag_test.go +++ b/datamodel/high/base/tag_test.go @@ -4,66 +4,66 @@ package base import ( - "fmt" - lowmodel "github.com/pb33f/libopenapi/datamodel/low" - lowbase "github.com/pb33f/libopenapi/datamodel/low/base" - "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v3" - "testing" + "fmt" + lowmodel "github.com/pb33f/libopenapi/datamodel/low" + lowbase "github.com/pb33f/libopenapi/datamodel/low/base" + "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v3" + "testing" ) func TestNewTag(t *testing.T) { - var cNode yaml.Node + var cNode yaml.Node - yml := `name: chicken + yml := `name: chicken description: nuggets externalDocs: url: https://pb33f.io x-hack: code` - _ = yaml.Unmarshal([]byte(yml), &cNode) + _ = yaml.Unmarshal([]byte(yml), &cNode) - var lowTag lowbase.Tag - _ = lowmodel.BuildModel(&cNode, &lowTag) - _ = lowTag.Build(cNode.Content[0], nil) + var lowTag lowbase.Tag + _ = lowmodel.BuildModel(cNode.Content[0], &lowTag) + _ = lowTag.Build(cNode.Content[0], nil) - highTag := NewTag(&lowTag) + highTag := NewTag(&lowTag) - assert.Equal(t, "chicken", highTag.Name) - assert.Equal(t, "nuggets", highTag.Description) - assert.Equal(t, "https://pb33f.io", highTag.ExternalDocs.URL) - assert.Equal(t, "code", highTag.Extensions["x-hack"]) + assert.Equal(t, "chicken", highTag.Name) + assert.Equal(t, "nuggets", highTag.Description) + assert.Equal(t, "https://pb33f.io", highTag.ExternalDocs.URL) + assert.Equal(t, "code", highTag.Extensions["x-hack"]) - wentLow := highTag.GoLow() - assert.Equal(t, 5, wentLow.FindExtension("x-hack").ValueNode.Line) + wentLow := highTag.GoLow() + assert.Equal(t, 5, wentLow.FindExtension("x-hack").ValueNode.Line) } func ExampleNewTag() { - // create an example schema object - // this can be either JSON or YAML. - yml := ` + // create an example schema object + // this can be either JSON or YAML. + yml := ` name: Purchases description: All kinds of purchase related operations externalDocs: url: https://pb33f.io/purchases x-hack: code` - // unmarshal raw bytes - var node yaml.Node - _ = yaml.Unmarshal([]byte(yml), &node) + // unmarshal raw bytes + var node yaml.Node + _ = yaml.Unmarshal([]byte(yml), &node) - // build out the low-level model - var lowTag lowbase.Tag - _ = lowmodel.BuildModel(&node, &lowTag) - _ = lowTag.Build(node.Content[0], nil) + // build out the low-level model + var lowTag lowbase.Tag + _ = lowmodel.BuildModel(node.Content[0], &lowTag) + _ = lowTag.Build(node.Content[0], nil) - // build the high level tag - highTag := NewTag(&lowTag) + // build the high level tag + highTag := NewTag(&lowTag) - // print out the tag name - fmt.Print(highTag.Name) - // Output: Purchases + // print out the tag name + fmt.Print(highTag.Name) + // Output: Purchases } diff --git a/datamodel/high/base/xml_test.go b/datamodel/high/base/xml_test.go index 4633e55..01d2051 100644 --- a/datamodel/high/base/xml_test.go +++ b/datamodel/high/base/xml_test.go @@ -4,33 +4,33 @@ package base import ( - "fmt" - lowmodel "github.com/pb33f/libopenapi/datamodel/low" - lowbase "github.com/pb33f/libopenapi/datamodel/low/base" - "gopkg.in/yaml.v3" + "fmt" + lowmodel "github.com/pb33f/libopenapi/datamodel/low" + lowbase "github.com/pb33f/libopenapi/datamodel/low/base" + "gopkg.in/yaml.v3" ) func ExampleNewXML() { - // create an example schema object - // this can be either JSON or YAML. - yml := ` + // create an example schema object + // this can be either JSON or YAML. + yml := ` namespace: https://pb33f.io/schema prefix: sample` - // unmarshal raw bytes - var node yaml.Node - _ = yaml.Unmarshal([]byte(yml), &node) + // unmarshal raw bytes + var node yaml.Node + _ = yaml.Unmarshal([]byte(yml), &node) - // build out the low-level model - var lowXML lowbase.XML - _ = lowmodel.BuildModel(&node, &lowXML) - _ = lowXML.Build(node.Content[0], nil) + // build out the low-level model + var lowXML lowbase.XML + _ = lowmodel.BuildModel(node.Content[0], &lowXML) + _ = lowXML.Build(node.Content[0], nil) - // build the high level tag - highXML := NewXML(&lowXML) + // build the high level tag + highXML := NewXML(&lowXML) - // print out the XML namespace - fmt.Print(highXML.Namespace) - // Output: https://pb33f.io/schema + // print out the XML namespace + fmt.Print(highXML.Namespace) + // Output: https://pb33f.io/schema } diff --git a/datamodel/high/v3/response_test.go b/datamodel/high/v3/response_test.go index fee72c4..57d2db8 100644 --- a/datamodel/high/v3/response_test.go +++ b/datamodel/high/v3/response_test.go @@ -36,7 +36,7 @@ links: idx := index.NewSpecIndex(&idxNode) var n v3.Response - _ = low.BuildModel(&idxNode, &n) + _ = low.BuildModel(idxNode.Content[0], &n) _ = n.Build(idxNode.Content[0], idx) r := NewResponse(&n) diff --git a/datamodel/low/base/discriminator_test.go b/datamodel/low/base/discriminator_test.go index 37de719..8e5f654 100644 --- a/datamodel/low/base/discriminator_test.go +++ b/datamodel/low/base/discriminator_test.go @@ -20,7 +20,7 @@ mapping: assert.NoError(t, mErr) var n Discriminator - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) assert.Equal(t, "nothing", n.FindMappingValue("something").Value) assert.Nil(t, n.FindMappingValue("freshCakes")) diff --git a/datamodel/low/base/example_test.go b/datamodel/low/base/example_test.go index e2be3d3..a7d3444 100644 --- a/datamodel/low/base/example_test.go +++ b/datamodel/low/base/example_test.go @@ -23,7 +23,7 @@ x-cake: hot` idx := index.NewSpecIndex(&idxNode) var n Example - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) @@ -49,7 +49,7 @@ x-cake: hot` idx := index.NewSpecIndex(&idxNode) var n Example - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) @@ -76,7 +76,7 @@ value: idx := index.NewSpecIndex(&idxNode) var n Example - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) @@ -107,7 +107,7 @@ value: idx := index.NewSpecIndex(&idxNode) var n Example - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/base/external_doc_test.go b/datamodel/low/base/external_doc_test.go index d309ab9..b261674 100644 --- a/datamodel/low/base/external_doc_test.go +++ b/datamodel/low/base/external_doc_test.go @@ -41,7 +41,7 @@ x-b33f: princess` idx := index.NewSpecIndex(&idxNode) var n ExternalDoc - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/base/info_test.go b/datamodel/low/base/info_test.go index b36c1d2..1184373 100644 --- a/datamodel/low/base/info_test.go +++ b/datamodel/low/base/info_test.go @@ -31,7 +31,7 @@ x-cli-name: pizza cli` idx := index.NewSpecIndex(&idxNode) var n Info - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/base/schema_proxy_test.go b/datamodel/low/base/schema_proxy_test.go index 3778a90..f4a7466 100644 --- a/datamodel/low/base/schema_proxy_test.go +++ b/datamodel/low/base/schema_proxy_test.go @@ -17,7 +17,7 @@ func TestSchemaProxy_Build(t *testing.T) { var idxNode yaml.Node _ = yaml.Unmarshal([]byte(yml), &idxNode) - err := sch.Build(&idxNode, nil) + err := sch.Build(idxNode.Content[0], nil) assert.NoError(t, err) assert.Equal(t, "something", sch.Schema().Description.Value) assert.Empty(t, sch.GetSchemaReference()) diff --git a/datamodel/low/base/schema_test.go b/datamodel/low/base/schema_test.go index 72ce849..c8ff3d8 100644 --- a/datamodel/low/base/schema_test.go +++ b/datamodel/low/base/schema_test.go @@ -125,7 +125,7 @@ func Test_Schema(t *testing.T) { assert.NoError(t, mErr) sch := Schema{} - mbErr := low.BuildModel(&rootNode, &sch) + mbErr := low.BuildModel(rootNode.Content[0], &sch) assert.NoError(t, mbErr) schErr := sch.Build(rootNode.Content[0], nil) @@ -280,7 +280,7 @@ examples: assert.NoError(t, mErr) sch := Schema{} - mbErr := low.BuildModel(&rootNode, &sch) + mbErr := low.BuildModel(rootNode.Content[0], &sch) assert.NoError(t, mbErr) schErr := sch.Build(rootNode.Content[0], nil) diff --git a/datamodel/low/base/tag_test.go b/datamodel/low/base/tag_test.go index c84c328..1502c3f 100644 --- a/datamodel/low/base/tag_test.go +++ b/datamodel/low/base/tag_test.go @@ -24,7 +24,7 @@ x-coffee: tasty` idx := index.NewSpecIndex(&idxNode) var n Tag - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/extraction_functions_test.go b/datamodel/low/extraction_functions_test.go index 0b5944a..431f02d 100644 --- a/datamodel/low/extraction_functions_test.go +++ b/datamodel/low/extraction_functions_test.go @@ -519,7 +519,7 @@ func TestExtractObjectRaw(t *testing.T) { var cNode yaml.Node _ = yaml.Unmarshal([]byte(yml), &cNode) - tag, err := ExtractObjectRaw[*pizza](&cNode, idx) + tag, err := ExtractObjectRaw[*pizza](cNode.Content[0], idx) assert.NoError(t, err) assert.NotNil(t, tag) assert.Equal(t, "hello pizza", tag.Description.Value) @@ -1143,8 +1143,7 @@ func TestExtractMapFlat_DoubleRef(t *testing.T) { yml := `components: schemas: stank: - things: - almostWork: 99` + almostWork: 99` var idxNode yaml.Node mErr := yaml.Unmarshal([]byte(yml), &idxNode) diff --git a/datamodel/low/model_builder.go b/datamodel/low/model_builder.go index da5d926..ac64bf9 100644 --- a/datamodel/low/model_builder.go +++ b/datamodel/low/model_builder.go @@ -46,7 +46,7 @@ func BuildModel(node *yaml.Node, model interface{}) error { var vn, kn *yaml.Node for _, tryCase := range cases { - kn, vn = utils.FindKeyNode(utils.ConvertCase(fName, tryCase), node.Content) + kn, vn = utils.FindKeyNodeTop(utils.ConvertCase(fName, tryCase), node.Content) if vn != nil { break } diff --git a/datamodel/low/model_builder_test.go b/datamodel/low/model_builder_test.go index e658534..900793a 100644 --- a/datamodel/low/model_builder_test.go +++ b/datamodel/low/model_builder_test.go @@ -104,7 +104,7 @@ there: assert.NoError(t, mErr) hd := hotdog{} - cErr := BuildModel(&rootNode, &hd) + cErr := BuildModel(rootNode.Content[0], &hd) assert.Equal(t, 200, hd.Fat.Value) assert.Equal(t, 3, hd.Fat.ValueNode.Line) assert.Equal(t, true, hd.Grilled.Value) @@ -156,7 +156,7 @@ func TestBuildModel_UseUnsupportedPrimitive(t *testing.T) { mErr := yaml.Unmarshal([]byte(yml), &rootNode) assert.NoError(t, mErr) - cErr := BuildModel(&rootNode, &ns) + cErr := BuildModel(rootNode.Content[0], &ns) assert.Error(t, cErr) assert.Empty(t, ns.cake) @@ -183,7 +183,7 @@ thing: yeah` try := BuildModel(nil, ins) assert.NoError(t, try) - cErr := BuildModel(&rootNode, ins) + cErr := BuildModel(rootNode.Content[0], ins) assert.NoError(t, cErr) assert.Empty(t, ins.PathItems.Value) assert.Empty(t, ins.Extensions.Value) @@ -205,7 +205,7 @@ func TestSetField_NodeRefAny_Error(t *testing.T) { mErr := yaml.Unmarshal([]byte(yml), &rootNode) assert.NoError(t, mErr) - try := BuildModel(&rootNode, ins) + try := BuildModel(rootNode.Content[0], ins) assert.Error(t, try) } @@ -226,7 +226,7 @@ func TestSetField_MapHelperWrapped(t *testing.T) { mErr := yaml.Unmarshal([]byte(yml), &rootNode) assert.NoError(t, mErr) - try := BuildModel(&rootNode, ins) + try := BuildModel(rootNode.Content[0], ins) assert.NoError(t, try) assert.Len(t, ins.Thing.Value, 3) } @@ -247,7 +247,7 @@ func TestSetField_MapHelper(t *testing.T) { mErr := yaml.Unmarshal([]byte(yml), &rootNode) assert.NoError(t, mErr) - try := BuildModel(&rootNode, ins) + try := BuildModel(rootNode.Content[0], ins) assert.NoError(t, try) assert.Len(t, ins.Thing, 3) } @@ -268,7 +268,7 @@ func TestSetField_ArrayHelper(t *testing.T) { mErr := yaml.Unmarshal([]byte(yml), &rootNode) assert.NoError(t, mErr) - try := BuildModel(&rootNode, ins) + try := BuildModel(rootNode.Content[0], ins) assert.NoError(t, try) assert.Len(t, ins.Thing.Value, 3) } @@ -316,7 +316,7 @@ func TestBuildModelAsync(t *testing.T) { var wg sync.WaitGroup var errors []error wg.Add(1) - BuildModelAsync(&rootNode, ins, &wg, &errors) + BuildModelAsync(rootNode.Content[0], ins, &wg, &errors) wg.Wait() assert.Len(t, ins.Thing.Value, 3) @@ -340,7 +340,7 @@ func TestBuildModelAsync_Error(t *testing.T) { var wg sync.WaitGroup var errors []error wg.Add(1) - BuildModelAsync(&rootNode, ins, &wg, &errors) + BuildModelAsync(rootNode.Content[0], ins, &wg, &errors) wg.Wait() assert.Len(t, errors, 1) assert.Len(t, ins.Thing, 0) diff --git a/datamodel/low/v2/paths.go b/datamodel/low/v2/paths.go index e871bf1..9725e34 100644 --- a/datamodel/low/v2/paths.go +++ b/datamodel/low/v2/paths.go @@ -4,9 +4,12 @@ package v2 import ( + "crypto/sha256" + "fmt" "github.com/pb33f/libopenapi/datamodel/low" "github.com/pb33f/libopenapi/index" "gopkg.in/yaml.v3" + "sort" "strings" ) @@ -26,6 +29,16 @@ func (p *Paths) FindPath(path string) *low.ValueReference[*PathItem] { return nil } +// FindPathAndKey attempts to locate a PathItem instance, given a path key. +func (p *Paths) FindPathAndKey(path string) (*low.KeyReference[string], *low.ValueReference[*PathItem]) { + for k, j := range p.PathItems { + if k.Value == path { + return &k, &j + } + } + return nil, nil +} + // FindExtension will attempt to locate an extension value given a name. func (p *Paths) FindExtension(ext string) *low.ValueReference[any] { return low.FindItemInMap[any](ext, p.Extensions) @@ -96,3 +109,25 @@ func (p *Paths) Build(root *yaml.Node, idx *index.SpecIndex) error { p.PathItems = pathsMap return nil } + +// Hash will return a consistent SHA256 Hash of the PathItem object +func (p *Paths) Hash() [32]byte { + var f []string + l := make([]string, len(p.PathItems)) + keys := make(map[string]low.ValueReference[*PathItem]) + z := 0 + for k := range p.PathItems { + keys[k.Value] = p.PathItems[k] + l[z] = k.Value + z++ + } + sort.Strings(l) + for k := range l { + f = append(f, low.GenerateHashString(keys[l[k]].Value)) + } + for k := range p.Extensions { + f = append(f, fmt.Sprintf("%s-%x", k.Value, + sha256.Sum256([]byte(fmt.Sprint(p.Extensions[k].Value))))) + } + return sha256.Sum256([]byte(strings.Join(f, "|"))) +} diff --git a/datamodel/low/v2/swagger.go b/datamodel/low/v2/swagger.go index be61a46..3b43bd7 100644 --- a/datamodel/low/v2/swagger.go +++ b/datamodel/low/v2/swagger.go @@ -111,7 +111,7 @@ type Swagger struct { SpecInfo *datamodel.SpecInfo } -// FindExte +// FindExtension locates an extension from the root of the Swagger document. func (s *Swagger) FindExtension(ext string) *low.ValueReference[any] { return low.FindItemInMap[any](ext, s.Extensions) } @@ -129,7 +129,7 @@ func CreateDocument(info *datamodel.SpecInfo) (*Swagger, []error) { var errors []error // build out swagger scalar variables. - _ = low.BuildModel(info.RootNode, &doc) + _ = low.BuildModel(info.RootNode.Content[0], &doc) // extract externalDocs extDocs, err := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode, idx) diff --git a/datamodel/low/v2/swagger_test.go b/datamodel/low/v2/swagger_test.go index 392f9d0..86baff0 100644 --- a/datamodel/low/v2/swagger_test.go +++ b/datamodel/low/v2/swagger_test.go @@ -44,6 +44,7 @@ func BenchmarkCreateDocument(b *testing.B) { func TestCreateDocument(t *testing.T) { initTest() + doc := doc assert.Equal(t, "2.0", doc.SpecInfo.Version) assert.Equal(t, "1.0.6", doc.Info.Value.Version.Value) assert.Equal(t, "petstore.swagger.io", doc.Host.Value) diff --git a/datamodel/low/v3/components_test.go b/datamodel/low/v3/components_test.go index 98069e9..e385337 100644 --- a/datamodel/low/v3/components_test.go +++ b/datamodel/low/v3/components_test.go @@ -70,7 +70,7 @@ func TestComponents_Build_Success(t *testing.T) { idx := index.NewSpecIndex(&idxNode) var n Components - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) @@ -93,9 +93,9 @@ func TestComponents_Build_Success(t *testing.T) { assert.Equal(t, "fifteen of many", n.FindLink("fifteen").Value.Description.Value) assert.Equal(t, "sixteen of many", n.FindLink("sixteen").Value.Description.Value) assert.Equal(t, "seventeen of many", - n.FindCallback("seventeen").Value.FindExpression("{reference}").Value.Description.Value) + n.FindCallback("seventeen").Value.FindExpression("{reference}").Value.Post.Value.Description.Value) assert.Equal(t, "eighteen of many", - n.FindCallback("eighteen").Value.FindExpression("{raference}").Value.Description.Value) + n.FindCallback("eighteen").Value.FindExpression("{raference}").Value.Post.Value.Description.Value) } diff --git a/datamodel/low/v3/constants.go b/datamodel/low/v3/constants.go index 2e8ac84..1955349 100644 --- a/datamodel/low/v3/constants.go +++ b/datamodel/low/v3/constants.go @@ -16,6 +16,7 @@ const ( CallbacksLabel = "callbacks" ContentLabel = "content" PathsLabel = "paths" + PathLabel = "path" WebhooksLabel = "webhooks" JSONSchemaDialectLabel = "jsonSchemaDialect" GetLabel = "get" diff --git a/datamodel/low/v3/encoding_test.go b/datamodel/low/v3/encoding_test.go index df56b06..9fc39df 100644 --- a/datamodel/low/v3/encoding_test.go +++ b/datamodel/low/v3/encoding_test.go @@ -28,7 +28,7 @@ explode: true` idx := index.NewSpecIndex(&idxNode) var n Encoding - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/v3/header_test.go b/datamodel/low/v3/header_test.go index a16b499..b1899fe 100644 --- a/datamodel/low/v3/header_test.go +++ b/datamodel/low/v3/header_test.go @@ -49,7 +49,7 @@ content: idx := index.NewSpecIndex(&idxNode) var n Header - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/v3/link_test.go b/datamodel/low/v3/link_test.go index 4ea9d69..dbf8b9c 100644 --- a/datamodel/low/v3/link_test.go +++ b/datamodel/low/v3/link_test.go @@ -30,7 +30,7 @@ x-linky: slinky idx := index.NewSpecIndex(&idxNode) var n Link - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/v3/oauth_flows_test.go b/datamodel/low/v3/oauth_flows_test.go index 7afe95a..7ee3f18 100644 --- a/datamodel/low/v3/oauth_flows_test.go +++ b/datamodel/low/v3/oauth_flows_test.go @@ -27,7 +27,7 @@ x-tasty: herbs idx := index.NewSpecIndex(&idxNode) var n OAuthFlow - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/v3/operation_test.go b/datamodel/low/v3/operation_test.go index 7c6004c..8ae4ca0 100644 --- a/datamodel/low/v3/operation_test.go +++ b/datamodel/low/v3/operation_test.go @@ -46,7 +46,7 @@ servers: idx := index.NewSpecIndex(&idxNode) var n Operation - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/v3/parameter_test.go b/datamodel/low/v3/parameter_test.go index d72eae5..6a2dc7f 100644 --- a/datamodel/low/v3/parameter_test.go +++ b/datamodel/low/v3/parameter_test.go @@ -51,7 +51,7 @@ content: idx := index.NewSpecIndex(&idxNode) var n Parameter - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/v3/paths.go b/datamodel/low/v3/paths.go index 28bb254..1d42d03 100644 --- a/datamodel/low/v3/paths.go +++ b/datamodel/low/v3/paths.go @@ -4,11 +4,13 @@ package v3 import ( + "crypto/sha256" "fmt" "github.com/pb33f/libopenapi/datamodel/low" "github.com/pb33f/libopenapi/index" "github.com/pb33f/libopenapi/utils" "gopkg.in/yaml.v3" + "sort" "strings" ) @@ -122,3 +124,25 @@ func (p *Paths) Build(root *yaml.Node, idx *index.SpecIndex) error { p.PathItems = pathsMap return nil } + +// Hash will return a consistent SHA256 Hash of the PathItem object +func (p *Paths) Hash() [32]byte { + var f []string + l := make([]string, len(p.PathItems)) + keys := make(map[string]low.ValueReference[*PathItem]) + z := 0 + for k := range p.PathItems { + keys[k.Value] = p.PathItems[k] + l[z] = k.Value + z++ + } + sort.Strings(l) + for k := range l { + f = append(f, low.GenerateHashString(keys[l[k]].Value)) + } + for k := range p.Extensions { + f = append(f, fmt.Sprintf("%s-%x", k.Value, + sha256.Sum256([]byte(fmt.Sprint(p.Extensions[k].Value))))) + } + return sha256.Sum256([]byte(strings.Join(f, "|"))) +} diff --git a/datamodel/low/v3/request_body_test.go b/datamodel/low/v3/request_body_test.go index 72b38f9..8cebd91 100644 --- a/datamodel/low/v3/request_body_test.go +++ b/datamodel/low/v3/request_body_test.go @@ -25,7 +25,7 @@ x-requesto: presto` idx := index.NewSpecIndex(&idxNode) var n RequestBody - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) @@ -47,7 +47,7 @@ func TestRequestBody_Fail(t *testing.T) { idx := index.NewSpecIndex(&idxNode) var n RequestBody - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/v3/security_scheme_test.go b/datamodel/low/v3/security_scheme_test.go index 1067b1c..aaa3fc8 100644 --- a/datamodel/low/v3/security_scheme_test.go +++ b/datamodel/low/v3/security_scheme_test.go @@ -52,7 +52,7 @@ x-milk: please` idx := index.NewSpecIndex(&idxNode) var n SecurityScheme - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/datamodel/low/v3/server_test.go b/datamodel/low/v3/server_test.go index bd60757..ee74d6f 100644 --- a/datamodel/low/v3/server_test.go +++ b/datamodel/low/v3/server_test.go @@ -26,7 +26,7 @@ variables: idx := index.NewSpecIndex(&idxNode) var n Server - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) @@ -48,7 +48,7 @@ description: high quality software for developers.` idx := index.NewSpecIndex(&idxNode) var n Server - err := low.BuildModel(&idxNode, &n) + err := low.BuildModel(idxNode.Content[0], &n) assert.NoError(t, err) err = n.Build(idxNode.Content[0], idx) diff --git a/what-changed/model/path_item.go b/what-changed/model/path_item.go index ecde547..205965b 100644 --- a/what-changed/model/path_item.go +++ b/what-changed/model/path_item.go @@ -137,10 +137,32 @@ func ComparePathItems(l, r any) *PathItemChanges { return nil } - props = append(props, compareOpenAPIPathItem(lPath, rPath, &changes, pc)...) + // description + props = append(props, &PropertyCheck{ + LeftNode: lPath.Description.ValueNode, + RightNode: rPath.Description.ValueNode, + Label: v3.DescriptionLabel, + Changes: &changes, + Breaking: false, + Original: lPath, + New: lPath, + }) + + // summary + props = append(props, &PropertyCheck{ + LeftNode: lPath.Summary.ValueNode, + RightNode: rPath.Summary.ValueNode, + Label: v3.SummaryLabel, + Changes: &changes, + Breaking: false, + Original: lPath, + New: lPath, + }) + + compareOpenAPIPathItem(lPath, rPath, &changes, pc) } - CheckProperties(props) + //CheckProperties(props) pc.Changes = changes return pc } @@ -380,31 +402,9 @@ func checkParameters(lParams, rParams []low.ValueReference[low.IsParameter], cha pc.ParameterChanges = paramChanges } -func compareOpenAPIPathItem(lPath, rPath *v3.PathItem, changes *[]*Change, pc *PathItemChanges) []*PropertyCheck { +func compareOpenAPIPathItem(lPath, rPath *v3.PathItem, changes *[]*Change, pc *PathItemChanges) { - var props []*PropertyCheck - - // description - props = append(props, &PropertyCheck{ - LeftNode: lPath.Description.ValueNode, - RightNode: rPath.Description.ValueNode, - Label: v3.DescriptionLabel, - Changes: changes, - Breaking: false, - Original: lPath, - New: lPath, - }) - - // summary - props = append(props, &PropertyCheck{ - LeftNode: lPath.Summary.ValueNode, - RightNode: rPath.Summary.ValueNode, - Label: v3.SummaryLabel, - Changes: changes, - Breaking: false, - Original: lPath, - New: lPath, - }) + //var props []*PropertyCheck totalOps := 0 opChan := make(chan opCheck) @@ -578,7 +578,6 @@ func compareOpenAPIPathItem(lPath, rPath *v3.PathItem, changes *[]*Change, pc *P } } pc.ExtensionChanges = CompareExtensions(lPath.Extensions, rPath.Extensions) - return props } func checkOperation(l, r any, done chan opCheck, method string) {