fix: fixed tests after merge

This commit is contained in:
Tristan Cartledge
2023-11-27 17:05:37 +00:00
parent 2de65e4ca0
commit 785824a271
23 changed files with 194 additions and 220 deletions

View File

@@ -6,6 +6,7 @@ package base
import (
low2 "github.com/pb33f/libopenapi/datamodel/high"
low "github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/pb33f/libopenapi/orderedmap"
"gopkg.in/yaml.v3"
)
@@ -20,7 +21,7 @@ import (
// v3 - https://spec.openapis.org/oas/v3.1.0#discriminator-object
type Discriminator struct {
PropertyName string `json:"propertyName,omitempty" yaml:"propertyName,omitempty"`
Mapping map[string]string `json:"mapping,omitempty" yaml:"mapping,omitempty"`
Mapping orderedmap.Map[string, string] `json:"mapping,omitempty" yaml:"mapping,omitempty"`
low *low.Discriminator
}
@@ -29,9 +30,9 @@ func NewDiscriminator(disc *low.Discriminator) *Discriminator {
d := new(Discriminator)
d.low = disc
d.PropertyName = disc.PropertyName.Value
mapping := make(map[string]string)
for k, v := range disc.Mapping.Value {
mapping[k.Value] = v.Value
mapping := orderedmap.New[string, string]()
for pair := disc.Mapping.Value.First(); pair != nil; pair = pair.Next() {
mapping.Set(pair.Key().Value, pair.Value().Value)
}
d.Mapping = mapping
return d

View File

@@ -5,16 +5,16 @@ package base
import (
"fmt"
"strings"
"testing"
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"strings"
"testing"
)
func TestNewDiscriminator(t *testing.T) {
var cNode yaml.Node
yml := `propertyName: coffee
@@ -31,17 +31,15 @@ mapping:
highDiscriminator := NewDiscriminator(&lowDiscriminator)
assert.Equal(t, "coffee", highDiscriminator.PropertyName)
assert.Equal(t, "in the morning", highDiscriminator.Mapping["fogCleaner"])
assert.Equal(t, "in the morning", highDiscriminator.Mapping.GetOrZero("fogCleaner"))
assert.Equal(t, 3, highDiscriminator.GoLow().FindMappingValue("fogCleaner").ValueNode.Line)
// render the example as YAML
rendered, _ := highDiscriminator.Render()
assert.Equal(t, strings.TrimSpace(string(rendered)), yml)
}
func ExampleNewDiscriminator() {
// create a yaml representation of a discriminator (can be JSON, doesn't matter)
yml := `propertyName: coffee
mapping:
@@ -59,6 +57,6 @@ mapping:
highDiscriminator := NewDiscriminator(&lowDiscriminator)
// print out a mapping defined for the discriminator.
fmt.Print(highDiscriminator.Mapping["coffee"])
fmt.Print(highDiscriminator.Mapping.GetOrZero("coffee"))
// Output: in the morning
}

View File

@@ -5,13 +5,14 @@ package base
import (
"context"
"strings"
"testing"
"github.com/pb33f/libopenapi/datamodel/low"
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/pb33f/libopenapi/index"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"strings"
"testing"
)
func TestDynamicValue_Render_A(t *testing.T) {
@@ -57,7 +58,6 @@ func TestDynamicValue_Render_Float64(t *testing.T) {
}
func TestDynamicValue_Render_Ptr(t *testing.T) {
type cake struct {
Cake string
}
@@ -68,7 +68,6 @@ func TestDynamicValue_Render_Ptr(t *testing.T) {
}
func TestDynamicValue_Render_PtrRenderable(t *testing.T) {
tag := &Tag{
Name: "cake",
}
@@ -79,7 +78,6 @@ func TestDynamicValue_Render_PtrRenderable(t *testing.T) {
}
func TestDynamicValue_RenderInline(t *testing.T) {
tag := &Tag{
Name: "cake",
}
@@ -90,7 +88,6 @@ func TestDynamicValue_RenderInline(t *testing.T) {
}
func TestDynamicValue_MarshalYAMLInline(t *testing.T) {
const ymlComponents = `components:
schemas:
rice:
@@ -130,11 +127,10 @@ func TestDynamicValue_MarshalYAMLInline(t *testing.T) {
// convert node into yaml
bits, _ := yaml.Marshal(rend)
assert.Equal(t, "properties:\n rice:\n type: array\n items:\n type: string", strings.TrimSpace(string(bits)))
assert.Equal(t, "properties:\n rice:\n $ref: '#/components/schemas/rice'", strings.TrimSpace(string(bits)))
}
func TestDynamicValue_MarshalYAMLInline_Error(t *testing.T) {
const ymlComponents = `components:
schemas:
rice:

View File

@@ -231,7 +231,7 @@ func TestNewDocument_Components_Schemas(t *testing.T) {
assert.Len(t, d.Schema().Required, 2)
assert.True(t, d.Schema().AdditionalProperties.B)
assert.Equal(t, "drinkType", d.Schema().Discriminator.PropertyName)
assert.Equal(t, "some value", d.Schema().Discriminator.Mapping["drink"])
assert.Equal(t, "some value", d.Schema().Discriminator.Mapping.GetOrZero("drink"))
assert.Equal(t, 516, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Line)
assert.Equal(t, 23, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Column)
@@ -300,8 +300,8 @@ func TestNewDocument_Components_SecuritySchemes(t *testing.T) {
assert.Equal(t, "an oAuth security scheme", oAuth.Description)
assert.Equal(t, 375, oAuth.GoLow().Description.ValueNode.Line)
assert.Equal(t, 20, oAuth.GoLow().Description.ValueNode.Column)
assert.Equal(t, 2, len(oAuth.Flows.Implicit.Scopes))
assert.Equal(t, "read all burgers", oAuth.Flows.Implicit.Scopes["read:burgers"])
assert.Equal(t, 2, oAuth.Flows.Implicit.Scopes.Len())
assert.Equal(t, "read all burgers", oAuth.Flows.Implicit.Scopes.GetOrZero("read:burgers"))
assert.Equal(t, "https://pb33f.io/oauth", oAuth.Flows.AuthorizationCode.AuthorizationUrl)
// check the lowness is low.
@@ -553,7 +553,7 @@ func TestCircularReferencesDoc(t *testing.T) {
lDoc, err := lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
assert.Len(t, utils.UnwrapErrors(err), 3)
d := NewDocument(lDoc)
assert.Len(t, d.Components.Schemas, 9)
assert.Equal(t, 9, d.Components.Schemas.Len())
assert.Len(t, d.Index.GetCircularReferences(), 3)
}

View File

@@ -6,6 +6,7 @@ package v3
import (
"github.com/pb33f/libopenapi/datamodel/high"
low "github.com/pb33f/libopenapi/datamodel/low/v3"
"github.com/pb33f/libopenapi/orderedmap"
"gopkg.in/yaml.v3"
)
@@ -15,8 +16,7 @@ type OAuthFlow struct {
AuthorizationUrl string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
TokenUrl string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
RefreshUrl string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
// FIXME: Scopes must be converted to orderedmap.Map. Fix unmarshaling issue causing omitted `scopes` stanza on parsing.
Scopes map[string]string `json:"scopes,omitempty" yaml:"scopes,omitempty"`
Scopes orderedmap.Map[string, string] `json:"scopes,omitempty" yaml:"scopes,omitempty"`
Extensions map[string]any `json:"-" yaml:"-"`
low *low.OAuthFlow
}
@@ -28,9 +28,9 @@ func NewOAuthFlow(flow *low.OAuthFlow) *OAuthFlow {
o.TokenUrl = flow.TokenUrl.Value
o.AuthorizationUrl = flow.AuthorizationUrl.Value
o.RefreshUrl = flow.RefreshUrl.Value
scopes := map[string]string{}
for k, v := range flow.Scopes.Value {
scopes[k.Value] = v.Value
scopes := orderedmap.New[string, string]()
for pair := flow.Scopes.Value.First(); pair != nil; pair = pair.Next() {
scopes.Set(pair.Key().Value, pair.Value().Value)
}
o.Scopes = scopes
o.Extensions = high.ExtractExtensions(flow.Extensions)

View File

@@ -7,19 +7,20 @@ import (
"strings"
"testing"
"github.com/pb33f/libopenapi/orderedmap"
"github.com/stretchr/testify/assert"
)
func TestOAuthFlow_MarshalYAML(t *testing.T) {
scopes := orderedmap.New[string, string]()
scopes.Set("chicken", "nuggets")
scopes.Set("beefy", "soup")
oflow := &OAuthFlow{
AuthorizationUrl: "https://pb33f.io",
TokenUrl: "https://pb33f.io/token",
RefreshUrl: "https://pb33f.io/refresh",
Scopes: map[string]string{
"chicken": "nuggets",
"beefy": "soup",
},
Scopes: scopes,
}
rend, _ := oflow.Render()
@@ -45,5 +46,4 @@ x-burgers: why not?`
rend, _ = oflow.Render()
assert.Equal(t, desired, strings.TrimSpace(string(rend)))
}

View File

@@ -16,7 +16,6 @@ import (
)
func TestNewOAuthFlows(t *testing.T) {
yml := `implicit:
authorizationUrl: https://pb33f.io/oauth/implicit
scopes:
@@ -49,10 +48,10 @@ clientCredentials:
r := NewOAuthFlows(&n)
assert.Len(t, r.Implicit.Scopes, 2)
assert.Len(t, r.AuthorizationCode.Scopes, 2)
assert.Len(t, r.Password.Scopes, 2)
assert.Len(t, r.ClientCredentials.Scopes, 2)
assert.Equal(t, 2, r.Implicit.Scopes.Len())
assert.Equal(t, 2, r.AuthorizationCode.Scopes.Len())
assert.Equal(t, 2, r.Password.Scopes.Len())
assert.Equal(t, 2, r.ClientCredentials.Scopes.Len())
assert.Equal(t, 2, r.GoLow().Implicit.Value.AuthorizationUrl.KeyNode.Line)
// now render it back out, and it should be identical!
@@ -83,8 +82,7 @@ clientCredentials:
CHIP:CHOP: microwave a sock`
// now modify it and render it back out, and it should be identical!
r.ClientCredentials.Scopes["CHIP:CHOP"] = "microwave a sock"
r.ClientCredentials.Scopes.Set("CHIP:CHOP", "microwave a sock")
rBytes, _ = r.Render()
assert.Equal(t, modified, strings.TrimSpace(string(rBytes)))
}

View File

@@ -5,9 +5,10 @@ package base
import (
"crypto/sha256"
"github.com/pb33f/libopenapi/datamodel/low"
"sort"
"strings"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/orderedmap"
)
// Discriminator is only used by OpenAPI 3+ documents, it represents a polymorphic discriminator used for schemas
@@ -21,14 +22,15 @@ import (
// v3 - https://spec.openapis.org/oas/v3.1.0#discriminator-object
type Discriminator struct {
PropertyName low.NodeReference[string]
Mapping low.NodeReference[map[low.KeyReference[string]]low.ValueReference[string]]
Mapping low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[string]]]
low.Reference
}
// FindMappingValue will return a ValueReference containing the string mapping value
func (d *Discriminator) FindMappingValue(key string) *low.ValueReference[string] {
for k, v := range d.Mapping.Value {
if k.Value == key {
for pair := d.Mapping.Value.First(); pair != nil; pair = pair.Next() {
if pair.Key().Value == key {
v := pair.Value()
return &v
}
}
@@ -37,20 +39,15 @@ func (d *Discriminator) FindMappingValue(key string) *low.ValueReference[string]
// Hash will return a consistent SHA256 Hash of the Discriminator object
func (d *Discriminator) Hash() [32]byte {
// calculate a hash from every property.
var f []string
if d.PropertyName.Value != "" {
f = append(f, d.PropertyName.Value)
}
propertyKeys := make([]string, 0, len(d.Mapping.Value))
for i := range d.Mapping.Value {
propertyKeys = append(propertyKeys, i.Value)
}
sort.Strings(propertyKeys)
for k := range propertyKeys {
prop := d.FindMappingValue(propertyKeys[k])
f = append(f, prop.Value)
for pair := orderedmap.First(d.Mapping.Value); pair != nil; pair = pair.Next() {
f = append(f, pair.Value().Value)
}
return sha256.Sum256([]byte(strings.Join(f, "|")))
}

View File

@@ -549,7 +549,6 @@ func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecInde
// determine exclusive minimum type, bool (3.0) or int (3.1)
_, exMinLabel, exMinValue := utils.FindKeyNodeFullTop(ExclusiveMinimumLabel, root.Content)
if exMinValue != nil {
// if there is an index, determine if this a 3.0 or 3.1 schema
if idx != nil {
if idx.GetConfig().SpecInfo.VersionNumeric == 3.1 {
@@ -593,7 +592,6 @@ func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecInde
// determine exclusive maximum type, bool (3.0) or int (3.1)
_, exMaxLabel, exMaxValue := utils.FindKeyNodeFullTop(ExclusiveMaximumLabel, root.Content)
if exMaxValue != nil {
// if there is an index, determine if this a 3.0 or 3.1 schema
if idx != nil {
if idx.GetConfig().SpecInfo.VersionNumeric == 3.1 {
@@ -1038,62 +1036,40 @@ func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecInde
}
func buildPropertyMap(ctx context.Context, root *yaml.Node, idx *index.SpecIndex, label string) (*low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]], error) {
// for property, build in a new thread!
bChan := make(chan schemaProxyBuildResult)
buildProperty := func(ctx context.Context, label *yaml.Node, value *yaml.Node, c chan schemaProxyBuildResult, isRef bool,
refString string,
) {
c <- schemaProxyBuildResult{
k: low.KeyReference[string]{
KeyNode: label,
Value: label.Value,
},
v: low.ValueReference[*SchemaProxy]{
Value: &SchemaProxy{ctx: ctx, kn: label, vn: value, idx: idx, isReference: isRef, referenceLookup: refString},
ValueNode: value,
},
}
}
_, propLabel, propsNode := utils.FindKeyNodeFullTop(label, root.Content)
if propsNode != nil {
propertyMap := orderedmap.New[low.KeyReference[string], low.ValueReference[*SchemaProxy]]()
var currentProp *yaml.Node
totalProps := 0
for i, prop := range propsNode.Content {
if i%2 == 0 {
currentProp = prop
continue
}
foundCtx := ctx
// check our prop isn't reference
isRef := false
refString := ""
if h, _, l := utils.IsNodeRefValue(prop); h {
ref, _, _, fctx := low.LocateRefNodeWithContext(ctx, prop, idx)
ref, _, _, _ := low.LocateRefNodeWithContext(ctx, prop, idx)
if ref != nil {
isRef = true
prop = ref
refString = l
foundCtx = fctx
} else {
return nil, fmt.Errorf("schema properties build failed: cannot find reference %s, line %d, col %d",
prop.Content[1].Value, prop.Content[1].Line, prop.Content[1].Column)
}
}
totalProps++
go buildProperty(foundCtx, currentProp, prop, bChan, isRef, refString)
}
completedProps := 0
for completedProps < totalProps {
select {
case res := <-bChan:
completedProps++
propertyMap.Set(res.k, res.v)
}
propertyMap.Set(low.KeyReference[string]{
KeyNode: currentProp,
Value: currentProp.Value,
}, low.ValueReference[*SchemaProxy]{
Value: &SchemaProxy{ctx: ctx, kn: currentProp, vn: prop, idx: idx, isReference: isRef, referenceLookup: refString},
ValueNode: prop,
})
}
return &low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]{
Value: propertyMap,
KeyNode: propLabel,
@@ -1280,7 +1256,7 @@ func ExtractSchema(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) (
schNode = ref
if foundIdx != nil {
// TODO: check on this
//idx = foundIdx
// idx = foundIdx
}
ctx = nCtx
} else {

View File

@@ -10,6 +10,7 @@ import (
"strings"
"sync"
"github.com/pb33f/libopenapi/orderedmap"
"github.com/pb33f/libopenapi/utils"
"gopkg.in/yaml.v3"
)
@@ -389,25 +390,25 @@ func SetField(field *reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) er
field.Set(reflect.ValueOf(ref))
}
}
case reflect.TypeOf(NodeReference[map[KeyReference[string]]ValueReference[string]]{}):
case reflect.TypeOf(NodeReference[orderedmap.Map[KeyReference[string], ValueReference[string]]]{}):
if utils.IsNodeMap(valueNode) {
if field.CanSet() {
items := make(map[KeyReference[string]]ValueReference[string])
items := orderedmap.New[KeyReference[string], ValueReference[string]]()
var cf *yaml.Node
for i, sliceItem := range valueNode.Content {
if i%2 == 0 {
cf = sliceItem
continue
}
items[KeyReference[string]{
items.Set(KeyReference[string]{
Value: cf.Value,
KeyNode: cf,
}] = ValueReference[string]{
}, ValueReference[string]{
Value: sliceItem.Value,
ValueNode: sliceItem,
})
}
}
ref := NodeReference[map[KeyReference[string]]ValueReference[string]]{
ref := NodeReference[orderedmap.Map[KeyReference[string], ValueReference[string]]]{
Value: items,
KeyNode: keyNode,
ValueNode: valueNode,

View File

@@ -1,10 +1,12 @@
package low
import (
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"sync"
"testing"
"github.com/pb33f/libopenapi/orderedmap"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
)
type hotdog struct {
@@ -27,11 +29,10 @@ type hotdog struct {
LotsOfUnknowns []NodeReference[any]
Where map[string]NodeReference[any]
There map[string]NodeReference[string]
AllTheThings NodeReference[map[KeyReference[string]]ValueReference[string]]
AllTheThings NodeReference[orderedmap.Map[KeyReference[string], ValueReference[string]]]
}
func TestBuildModel_Mismatch(t *testing.T) {
yml := `crisps: are tasty`
var rootNode yaml.Node
@@ -42,11 +43,9 @@ func TestBuildModel_Mismatch(t *testing.T) {
cErr := BuildModel(&rootNode, &hd)
assert.NoError(t, cErr)
assert.Empty(t, hd.Name)
}
func TestBuildModel(t *testing.T) {
yml := `name: yummy
valueName: yammy
beef: true
@@ -135,19 +134,18 @@ allTheThings:
assert.Equal(t, 324938249028.98234892374892374923874823974, hd.Mustard.Value)
allTheThings := hd.AllTheThings.Value
for i := range allTheThings {
if i.Value == "beer" {
assert.Equal(t, "isGood", allTheThings[i].Value)
for pair := allTheThings.First(); pair != nil; pair = pair.Next() {
if pair.Key().Value == "beer" {
assert.Equal(t, "isGood", pair.Value().Value)
}
if i.Value == "cake" {
assert.Equal(t, "isNice", allTheThings[i].Value)
if pair.Key().Value == "cake" {
assert.Equal(t, "isNice", pair.Value().Value)
}
}
assert.NoError(t, cErr)
}
func TestBuildModel_UseCopyNotRef(t *testing.T) {
yml := `cake: -99999`
var rootNode yaml.Node
@@ -158,11 +156,9 @@ func TestBuildModel_UseCopyNotRef(t *testing.T) {
cErr := BuildModel(&rootNode, hd)
assert.Error(t, cErr)
assert.Empty(t, hd.Name)
}
func TestBuildModel_UseUnsupportedPrimitive(t *testing.T) {
type notSupported struct {
cake string
}
@@ -176,11 +172,9 @@ func TestBuildModel_UseUnsupportedPrimitive(t *testing.T) {
cErr := BuildModel(rootNode.Content[0], &ns)
assert.Error(t, cErr)
assert.Empty(t, ns.cake)
}
func TestBuildModel_UsingInternalConstructs(t *testing.T) {
type internal struct {
Extensions NodeReference[string]
PathItems NodeReference[string]
@@ -208,7 +202,6 @@ thing: yeah`
}
func TestSetField_NodeRefAny_Error(t *testing.T) {
type internal struct {
Thing []NodeReference[any]
}
@@ -224,11 +217,9 @@ func TestSetField_NodeRefAny_Error(t *testing.T) {
try := BuildModel(rootNode.Content[0], ins)
assert.Error(t, try)
}
func TestSetField_MapHelperWrapped(t *testing.T) {
type internal struct {
Thing KeyReference[map[KeyReference[string]]ValueReference[string]]
}
@@ -249,7 +240,6 @@ func TestSetField_MapHelperWrapped(t *testing.T) {
}
func TestSetField_MapHelper(t *testing.T) {
type internal struct {
Thing map[KeyReference[string]]ValueReference[string]
}
@@ -270,7 +260,6 @@ func TestSetField_MapHelper(t *testing.T) {
}
func TestSetField_ArrayHelper(t *testing.T) {
type internal struct {
Thing NodeReference[[]ValueReference[string]]
}
@@ -291,7 +280,6 @@ func TestSetField_ArrayHelper(t *testing.T) {
}
func TestSetField_Enum_Helper(t *testing.T) {
type internal struct {
Thing NodeReference[[]ValueReference[any]]
}
@@ -312,7 +300,6 @@ func TestSetField_Enum_Helper(t *testing.T) {
}
func TestSetField_Default_Helper(t *testing.T) {
type cake struct {
thing int
}
@@ -336,7 +323,6 @@ func TestSetField_Default_Helper(t *testing.T) {
}
func TestHandleSlicesOfInts(t *testing.T) {
type internal struct {
Thing NodeReference[[]ValueReference[any]]
}
@@ -377,7 +363,6 @@ func TestHandleSlicesOfBools(t *testing.T) {
}
func TestSetField_Ignore(t *testing.T) {
type Complex struct {
name string
}
@@ -401,7 +386,6 @@ func TestSetField_Ignore(t *testing.T) {
}
func TestBuildModelAsync(t *testing.T) {
type internal struct {
Thing KeyReference[map[KeyReference[string]]ValueReference[string]]
}
@@ -422,11 +406,9 @@ func TestBuildModelAsync(t *testing.T) {
BuildModelAsync(rootNode.Content[0], ins, &wg, &errors)
wg.Wait()
assert.Len(t, ins.Thing.Value, 3)
}
func TestBuildModelAsync_Error(t *testing.T) {
type internal struct {
Thing []NodeReference[any]
}
@@ -447,5 +429,4 @@ func TestBuildModelAsync_Error(t *testing.T) {
wg.Wait()
assert.Len(t, errors, 1)
assert.Len(t, ins.Thing, 0)
}

View File

@@ -2,14 +2,15 @@ package v3
import (
"fmt"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/utils"
"log/slog"
"net/http"
"net/url"
"os"
"testing"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/utils"
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/orderedmap"
"github.com/stretchr/testify/assert"
@@ -525,7 +526,7 @@ func TestCreateDocument_Components_Schemas(t *testing.T) {
components := doc.Components.Value
assert.NotNil(t, components)
assert.Len(t, components.Schemas.Value, 6)
assert.Equal(t, 6, components.Schemas.Value.Len())
burger := components.FindSchema("Burger").Value
assert.NotNil(t, burger)
@@ -539,7 +540,7 @@ func TestCreateDocument_Components_Schemas(t *testing.T) {
fries := components.FindSchema("Fries")
assert.NotNil(t, fries.Value)
assert.Len(t, fries.Value.Schema().Properties.Value, 3)
assert.Equal(t, 3, fries.Value.Schema().Properties.Value.Len())
p := fries.Value.Schema().FindProperty("favoriteDrink")
assert.Equal(t, "a frosty cold beverage can be coke or sprite",
p.Value.Schema().Description.Value)
@@ -549,7 +550,7 @@ func TestCreateDocument_Components_SecuritySchemes(t *testing.T) {
initTest()
components := doc.Components.Value
securitySchemes := components.SecuritySchemes.Value
assert.Len(t, securitySchemes, 3)
assert.Equal(t, 3, securitySchemes.Len())
apiKey := components.FindSecurityScheme("APIKeyScheme").Value
assert.NotNil(t, apiKey)
@@ -577,19 +578,19 @@ func TestCreateDocument_Components_Responses(t *testing.T) {
initTest()
components := doc.Components.Value
responses := components.Responses.Value
assert.Len(t, responses, 1)
assert.Equal(t, 1, responses.Len())
dressingResponse := components.FindResponse("DressingResponse")
assert.NotNil(t, dressingResponse.Value)
assert.Equal(t, "all the dressings for a burger.", dressingResponse.Value.Description.Value)
assert.Len(t, dressingResponse.Value.Content.Value, 1)
assert.Equal(t, 1, dressingResponse.Value.Content.Value.Len())
}
func TestCreateDocument_Components_Examples(t *testing.T) {
initTest()
components := doc.Components.Value
examples := components.Examples.Value
assert.Len(t, examples, 1)
assert.Equal(t, 1, examples.Len())
quarterPounder := components.FindExample("QuarterPounder")
assert.NotNil(t, quarterPounder.Value)
@@ -601,19 +602,19 @@ func TestCreateDocument_Components_RequestBodies(t *testing.T) {
initTest()
components := doc.Components.Value
requestBodies := components.RequestBodies.Value
assert.Len(t, requestBodies, 1)
assert.Equal(t, 1, requestBodies.Len())
burgerRequest := components.FindRequestBody("BurgerRequest")
assert.NotNil(t, burgerRequest.Value)
assert.Equal(t, "Give us the new burger!", burgerRequest.Value.Description.Value)
assert.Len(t, burgerRequest.Value.Content.Value, 1)
assert.Equal(t, 1, burgerRequest.Value.Content.Value.Len())
}
func TestCreateDocument_Components_Headers(t *testing.T) {
initTest()
components := doc.Components.Value
headers := components.Headers.Value
assert.Len(t, headers, 1)
assert.Equal(t, 1, headers.Len())
useOil := components.FindHeader("UseOil")
assert.NotNil(t, useOil.Value)
@@ -625,7 +626,7 @@ func TestCreateDocument_Components_Links(t *testing.T) {
initTest()
components := doc.Components.Value
links := components.Links.Value
assert.Len(t, links, 2)
assert.Equal(t, 2, links.Len())
locateBurger := components.FindLink("LocateBurger")
assert.NotNil(t, locateBurger.Value)
@@ -646,11 +647,11 @@ func TestCreateDocument_Doc_Security(t *testing.T) {
func TestCreateDocument_Callbacks(t *testing.T) {
initTest()
callbacks := doc.Components.Value.Callbacks.Value
assert.Len(t, callbacks, 1)
assert.Equal(t, 1, callbacks.Len())
bCallback := doc.Components.Value.FindCallback("BurgerCallback")
assert.NotNil(t, bCallback.Value)
assert.Len(t, callbacks, 1)
assert.Equal(t, 1, callbacks.Len())
exp := bCallback.Value.FindExpression("{$request.query.queryUrl}")
assert.NotNil(t, exp.Value)
@@ -791,7 +792,6 @@ func TestCreateDocument_YamlAnchor(t *testing.T) {
// build low-level document model
document, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
if err != nil {
fmt.Printf("error: %s\n", err.Error())
panic("cannot build document")
@@ -851,7 +851,6 @@ func ExampleCreateDocument() {
// build low-level document model
document, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
if err != nil {
fmt.Printf("error: %s\n", err.Error())
panic("cannot build document")

View File

@@ -5,12 +5,14 @@ package v3
import (
"context"
"testing"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/orderedmap"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"testing"
)
func TestHeader_Build(t *testing.T) {
@@ -168,7 +170,6 @@ func TestHeader_Build_Fail_Content(t *testing.T) {
}
func TestEncoding_Hash_n_Grab(t *testing.T) {
yml := `description: heady
required: true
deprecated: true
@@ -241,7 +242,6 @@ schema:
sch := n.GetSchema().Value.(*base.SchemaProxy).Schema()
assert.Len(t, sch.Type.Value.B, 2) // using multiple types for 3.1 testing.
assert.Equal(t, "what a good puppy", n.GetExample().Value)
assert.Len(t, n.GetExamples().Value, 1)
assert.Len(t, n.GetContent().Value.(map[low.KeyReference[string]]low.ValueReference[*MediaType]), 1)
assert.Equal(t, 1, orderedmap.Cast[low.KeyReference[string], low.ValueReference[*base.Example]](n.GetExamples().Value).Len())
assert.Equal(t, 1, orderedmap.Cast[low.KeyReference[string], low.ValueReference[*MediaType]](n.GetContent().Value).Len())
}

View File

@@ -5,11 +5,12 @@ package v3
import (
"context"
"testing"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"testing"
)
func TestMediaType_Build(t *testing.T) {
@@ -42,7 +43,7 @@ x-rock: and roll`
assert.Equal(t, "why?", n.FindExample("what").Value.Value.Value)
assert.Equal(t, "there?", n.FindExample("where").Value.Value.Value)
assert.True(t, n.FindPropertyEncoding("chicken").Value.Explode.Value)
assert.Len(t, n.GetAllExamples(), 2)
assert.Equal(t, n.GetAllExamples().Len(), 2)
}
func TestMediaType_Build_Fail_Schema(t *testing.T) {
@@ -76,7 +77,6 @@ func TestMediaType_Build_Fail_Examples(t *testing.T) {
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
assert.Error(t, err)
}
func TestMediaType_Build_Fail_Encoding(t *testing.T) {
@@ -97,7 +97,6 @@ func TestMediaType_Build_Fail_Encoding(t *testing.T) {
}
func TestMediaType_Hash(t *testing.T) {
yml := `schema:
type: string
example: a thing

View File

@@ -12,6 +12,7 @@ import (
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/orderedmap"
"github.com/pb33f/libopenapi/utils"
"gopkg.in/yaml.v3"
)
@@ -97,7 +98,7 @@ type OAuthFlow struct {
AuthorizationUrl low.NodeReference[string]
TokenUrl low.NodeReference[string]
RefreshUrl low.NodeReference[string]
Scopes low.NodeReference[map[low.KeyReference[string]]low.ValueReference[string]]
Scopes low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[string]]]
Extensions map[low.KeyReference[string]]low.ValueReference[any]
*low.Reference
}
@@ -109,7 +110,7 @@ func (o *OAuthFlow) GetExtensions() map[low.KeyReference[string]]low.ValueRefere
// FindScope attempts to locate a scope using a specified name.
func (o *OAuthFlow) FindScope(scope string) *low.ValueReference[string] {
return low.FindItemInMap[string](scope, o.Scopes.Value)
return low.FindItemInOrderedMap[string](scope, o.Scopes.Value)
}
// FindExtension attempts to locate an extension with a specified key
@@ -136,10 +137,10 @@ func (o *OAuthFlow) Hash() [32]byte {
if !o.RefreshUrl.IsEmpty() {
f = append(f, o.RefreshUrl.Value)
}
keys := make([]string, len(o.Scopes.Value))
keys := make([]string, orderedmap.Len(o.Scopes.Value))
z := 0
for k, v := range o.Scopes.Value {
keys[z] = fmt.Sprintf("%s-%s", k.Value, sha256.Sum256([]byte(fmt.Sprint(v.Value))))
for pair := orderedmap.First(o.Scopes.Value); pair != nil; pair = pair.Next() {
keys[z] = fmt.Sprintf("%s-%s", pair.Key().Value, sha256.Sum256([]byte(fmt.Sprint(pair.Value().Value))))
z++
}
sort.Strings(keys)

View File

@@ -5,16 +5,16 @@ package v3
import (
"context"
"testing"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/pb33f/libopenapi/index"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"testing"
)
func TestOperation_Build(t *testing.T) {
yml := `tags:
- meddy
- maddy
@@ -61,9 +61,9 @@ servers:
assert.Equal(t, "beefyBeef", n.OperationId.Value)
assert.Len(t, n.Parameters.Value, 2)
assert.Equal(t, "a requestBody", n.RequestBody.Value.Description.Value)
assert.Len(t, n.Responses.Value.Codes, 1)
assert.Equal(t, 1, n.Responses.Value.Codes.Len())
assert.Equal(t, "an OK response", n.Responses.Value.FindResponseByCode("200").Value.Description.Value)
assert.Len(t, n.Callbacks.Value, 1)
assert.Equal(t, 1, n.Callbacks.Value.Len())
assert.Equal(t, "a nice callback",
n.FindCallback("niceCallback").Value.FindExpression("ohISee").Value.Description.Value)
assert.True(t, n.Deprecated.Value)
@@ -76,7 +76,6 @@ servers:
}
func TestOperation_Build_FailDocs(t *testing.T) {
yml := `externalDocs:
$ref: #borked`
@@ -93,7 +92,6 @@ func TestOperation_Build_FailDocs(t *testing.T) {
}
func TestOperation_Build_FailParams(t *testing.T) {
yml := `parameters:
$ref: #borked`
@@ -110,7 +108,6 @@ func TestOperation_Build_FailParams(t *testing.T) {
}
func TestOperation_Build_FailRequestBody(t *testing.T) {
yml := `requestBody:
$ref: #borked`
@@ -127,7 +124,6 @@ func TestOperation_Build_FailRequestBody(t *testing.T) {
}
func TestOperation_Build_FailResponses(t *testing.T) {
yml := `responses:
$ref: #borked`
@@ -144,7 +140,6 @@ func TestOperation_Build_FailResponses(t *testing.T) {
}
func TestOperation_Build_FailCallbacks(t *testing.T) {
yml := `callbacks:
$ref: #borked`
@@ -161,7 +156,6 @@ func TestOperation_Build_FailCallbacks(t *testing.T) {
}
func TestOperation_Build_FailSecurity(t *testing.T) {
yml := `security:
$ref: #borked`
@@ -178,7 +172,6 @@ func TestOperation_Build_FailSecurity(t *testing.T) {
}
func TestOperation_Build_FailServers(t *testing.T) {
yml := `servers:
$ref: #borked`
@@ -195,7 +188,6 @@ func TestOperation_Build_FailServers(t *testing.T) {
}
func TestOperation_Hash_n_Grab(t *testing.T) {
yml := `tags:
- nice
- rice
@@ -282,14 +274,12 @@ x-mint: sweet`
assert.True(t, n.GetDeprecated().Value)
assert.Len(t, n.GetExtensions(), 1)
assert.Len(t, n.GetServers().Value.([]low.ValueReference[*Server]), 1)
assert.Len(t, n.GetCallbacks().Value, 1)
assert.Len(t, n.GetResponses().Value.(*Responses).Codes, 1)
assert.Equal(t, 1, n.GetCallbacks().Value.Len())
assert.Equal(t, 1, n.GetResponses().Value.(*Responses).Codes.Len())
assert.Nil(t, n.FindSecurityRequirement("I do not exist"))
}
func TestOperation_EmptySecurity(t *testing.T) {
yml := `
security: []`
@@ -305,5 +295,4 @@ security: []`
assert.NoError(t, err)
assert.Len(t, n.Security.Value, 0)
}

View File

@@ -5,12 +5,14 @@ package v3
import (
"context"
"testing"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/orderedmap"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"testing"
)
func TestParameter_Build(t *testing.T) {
@@ -172,7 +174,6 @@ func TestParameter_Build_Fail_Content(t *testing.T) {
}
func TestParameter_Hash_n_grab(t *testing.T) {
yml := `description: michelle, meddy and maddy
required: true
deprecated: false
@@ -275,11 +276,11 @@ content:
assert.True(t, n.GetRequired().Value)
assert.False(t, n.GetDeprecated().Value)
assert.False(t, n.GetAllowEmptyValue().Value)
assert.Len(t, n.GetSchema().Value.(*base.SchemaProxy).Schema().Properties.Value, 3)
assert.Equal(t, 3, n.GetSchema().Value.(*base.SchemaProxy).Schema().Properties.Value.Len())
assert.Equal(t, "beautiful", n.GetStyle().Value)
assert.True(t, n.GetAllowReserved().Value)
assert.True(t, n.GetExplode().Value)
assert.NotNil(t, n.GetExample().Value)
assert.Len(t, n.GetExamples().Value.(map[low.KeyReference[string]]low.ValueReference[*base.Example]), 2)
assert.Len(t, n.GetContent().Value.(map[low.KeyReference[string]]low.ValueReference[*MediaType]), 1)
assert.Equal(t, 2, orderedmap.Cast[low.KeyReference[string], low.ValueReference[*base.Example]](n.GetExamples().Value).Len())
assert.Equal(t, 1, orderedmap.Cast[low.KeyReference[string], low.ValueReference[*MediaType]](n.GetContent().Value).Len())
}

View File

@@ -5,12 +5,13 @@ package v3
import (
"context"
"testing"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/pb33f/libopenapi/index"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"testing"
)
func TestSecurityRequirement_Build(t *testing.T) {
@@ -29,7 +30,7 @@ func TestSecurityRequirement_Build(t *testing.T) {
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
assert.NoError(t, err)
assert.Len(t, n.Requirements.Value, 1)
assert.Equal(t, 1, n.Requirements.Value.Len())
assert.Equal(t, "read:me", n.FindRequirement("something")[0].Value)
assert.Equal(t, "write:me", n.FindRequirement("something")[1].Value)
assert.Nil(t, n.FindRequirement("none"))
@@ -72,7 +73,6 @@ x-milk: please`
assert.Equal(t, "please", n.FindExtension("x-milk").Value)
assert.Equal(t, "https://pb33f.io", n.Flows.Value.Implicit.Value.TokenUrl.Value)
assert.Len(t, n.GetExtensions(), 1)
}
func TestSecurityScheme_Build_Fail(t *testing.T) {

View File

@@ -5,15 +5,16 @@ package v3
import (
"context"
"testing"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/orderedmap"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"testing"
)
func TestServer_Build(t *testing.T) {
yml := `x-coffee: hot
url: https://pb33f.io
description: high quality software for developers.
@@ -48,11 +49,9 @@ variables:
low.GenerateHashString(s.Value))
assert.Len(t, n.GetExtensions(), 1)
}
func TestServer_Build_NoVars(t *testing.T) {
yml := `url: https://pb33f.io
description: high quality software for developers.`
@@ -68,6 +67,5 @@ description: high quality software for developers.`
assert.NoError(t, err)
assert.Equal(t, "https://pb33f.io", n.URL.Value)
assert.Equal(t, "high quality software for developers.", n.Description.Value)
assert.Len(t, n.Variables.Value, 0)
assert.Equal(t, 0, orderedmap.Len(n.Variables.Value))
}

View File

@@ -42,9 +42,11 @@ type wrapPair[K comparable, V any] struct {
*wk8orderedmap.Pair[K, V]
}
type ActionFunc[K comparable, V any] func(Pair[K, V]) error
type TranslateFunc[IN any, OUT any] func(IN) (OUT, error)
type ResultFunc[V any] func(V) error
type (
ActionFunc[K comparable, V any] func(Pair[K, V]) error
TranslateFunc[IN any, OUT any] func(IN) (OUT, error)
ResultFunc[V any] func(V) error
)
// New creates an ordered map generic object.
func New[K comparable, V any]() Map[K, V] {
@@ -63,6 +65,10 @@ func (o *wrapOrderedMap[K, V]) GetOrZero(k K) V {
}
func (o *wrapOrderedMap[K, V]) First() Pair[K, V] {
if o == nil {
return nil
}
pair := o.OrderedMap.Oldest()
if pair == nil {
return nil
@@ -174,6 +180,20 @@ func First[K comparable, V any](m Map[K, V]) Pair[K, V] {
return m.First()
}
// Cast converts `any` to `Map`.
func Cast[K comparable, V any](v any) Map[K, V] {
if v == nil {
return nil
}
m, ok := v.(*wrapOrderedMap[K, V])
if !ok {
return nil
}
return m
}
type jobStatus[T any] struct {
done chan struct{}
result T

View File

@@ -26,8 +26,8 @@ var changeMutex sync.Mutex
// CreateChange is a generic function that will create a Change of type T, populate all properties if set, and then
// add a pointer to Change[T] in the slice of Change pointers provided
func CreateChange(changes *[]*Change, changeType int, property string, leftValueNode, rightValueNode *yaml.Node,
breaking bool, originalObject, newObject any) *[]*Change {
breaking bool, originalObject, newObject any,
) *[]*Change {
// create a new context for the left and right nodes.
ctx := CreateContext(leftValueNode, rightValueNode)
c := &Change{
@@ -71,7 +71,8 @@ func CreateContext(l, r *yaml.Node) *ChangeContext {
}
func FlattenLowLevelMap[T any](
lowMap map[low.KeyReference[string]]low.ValueReference[T]) map[string]*low.ValueReference[T] {
lowMap map[low.KeyReference[string]]low.ValueReference[T],
) map[string]*low.ValueReference[T] {
flat := make(map[string]*low.ValueReference[T])
for i := range lowMap {
l := lowMap[i]
@@ -80,6 +81,19 @@ func FlattenLowLevelMap[T any](
return flat
}
func FlattenLowLevelOrderedMap[T any](
lowMap orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
) map[string]*low.ValueReference[T] {
flat := make(map[string]*low.ValueReference[T])
for pair := orderedmap.First(lowMap); pair != nil; pair = pair.Next() {
k := pair.Key()
l := pair.Value()
flat[k.Value] = &l
}
return flat
}
// CountBreakingChanges counts the number of changes in a slice that are breaking
func CountBreakingChanges(changes []*Change) int {
b := 0
@@ -99,7 +113,8 @@ func CountBreakingChanges(changes []*Change) int {
// properties like descriptions, summaries and other non-binding values, so a breakingRemove value can be tuned for
// these circumstances.
func CheckForObjectAdditionOrRemoval[T any](l, r map[string]*low.ValueReference[T], label string, changes *[]*Change,
breakingAdd, breakingRemove bool) {
breakingAdd, breakingRemove bool,
) {
var left, right T
if CheckSpecificObjectRemoved(l, r, label) {
left = l[label].GetValue()
@@ -129,7 +144,6 @@ func CheckSpecificObjectAdded[T any](l, r map[string]*T, label string) bool {
// CheckPropertyAdditionOrRemoval
// CheckForModification
func CheckProperties(properties []*PropertyCheck) {
// todo: make this async to really speed things up.
for _, n := range properties {
CheckPropertyAdditionOrRemoval(n.LeftNode, n.RightNode, n.Label, n.Changes, n.Breaking, n.Original, n.New)
@@ -139,7 +153,8 @@ func CheckProperties(properties []*PropertyCheck) {
// CheckPropertyAdditionOrRemoval will run both CheckForRemoval (first) and CheckForAddition (second)
func CheckPropertyAdditionOrRemoval[T any](l, r *yaml.Node,
label string, changes *[]*Change, breaking bool, orig, new T) {
label string, changes *[]*Change, breaking bool, orig, new T,
) {
CheckForRemoval[T](l, r, label, changes, breaking, orig, new)
CheckForAddition[T](l, r, label, changes, breaking, orig, new)
}
@@ -238,12 +253,14 @@ 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]],
changes *[]*Change, label string, compareFunc func(l, r T) R) map[string]R {
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]],
changes *[]*Change, label string) any {
changes *[]*Change, label string,
) any {
// do nothing
doNothing := func(l, r T) any {
return nil
@@ -266,8 +283,8 @@ func CheckMapForAdditionRemoval[T any](expLeft, expRight orderedmap.Map[low.KeyR
// 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]],
changes *[]*Change, label string, compareFunc func(l, r T) R, compare bool) map[string]R {
changes *[]*Change, label string, compareFunc func(l, r T) R, compare bool,
) map[string]R {
// stop concurrent threads screwing up changes.
var chLock sync.Mutex
@@ -331,7 +348,7 @@ func CheckMapForChangesWithComp[T any, R any](expLeft, expRight orderedmap.Map[l
go checkLeft(k, doneChan, lHashes, rHashes, lValues, rValues)
}
//check right example hashes
// check right example hashes
for k := range rHashes {
count++
go checkRightValue(k, doneChan, lHashes, rValues, changes, label, &chLock)
@@ -349,8 +366,8 @@ func CheckMapForChangesWithComp[T any, R any](expLeft, expRight orderedmap.Map[l
}
func checkRightValue[T any](k string, doneChan chan bool, f map[string]string, p map[string]low.ValueReference[T],
changes *[]*Change, label string, lock *sync.Mutex) {
changes *[]*Change, label string, lock *sync.Mutex,
) {
lhash := f[k]
if lhash == "" {
lock.Lock()
@@ -367,7 +384,8 @@ func checkRightValue[T any](k string, doneChan chan bool, f map[string]string, p
// ExtractStringValueSliceChanges will compare two low level string slices for changes.
func ExtractStringValueSliceChanges(lParam, rParam []low.ValueReference[string],
changes *[]*Change, label string, breaking bool) {
changes *[]*Change, label string, breaking bool,
) {
lKeys := make([]string, len(lParam))
rKeys := make([]string, len(rParam))
lValues := make(map[string]low.ValueReference[string])
@@ -404,7 +422,8 @@ func ExtractStringValueSliceChanges(lParam, rParam []low.ValueReference[string],
// ExtractRawValueSliceChanges will compare two low level interface{} slices for changes.
func ExtractRawValueSliceChanges(lParam, rParam []low.ValueReference[any],
changes *[]*Change, label string, breaking bool) {
changes *[]*Change, label string, breaking bool,
) {
lKeys := make([]string, len(lParam))
rKeys := make([]string, len(rParam))
lValues := make(map[string]low.ValueReference[any])

View File

@@ -64,8 +64,8 @@ func CompareDiscriminator(l, r *base.Discriminator) *DiscriminatorChanges {
CheckProperties(props)
// flatten maps
lMap := FlattenLowLevelMap[string](l.Mapping.Value)
rMap := FlattenLowLevelMap[string](r.Mapping.Value)
lMap := FlattenLowLevelOrderedMap[string](l.Mapping.Value)
rMap := FlattenLowLevelOrderedMap[string](r.Mapping.Value)
// check for removals, modifications and moves
for i := range lMap {
@@ -92,5 +92,4 @@ func CompareDiscriminator(l, r *base.Discriminator) *DiscriminatorChanges {
return nil
}
return dc
}

View File

@@ -6,6 +6,7 @@ package model
import (
"github.com/pb33f/libopenapi/datamodel/low"
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
"github.com/pb33f/libopenapi/orderedmap"
)
// OAuthFlowsChanges represents changes found between two OpenAPI OAuthFlows objects.
@@ -228,26 +229,26 @@ func CompareOAuthFlow(l, r *v3.OAuthFlow) *OAuthFlowChanges {
CheckProperties(props)
for k, v := range l.Scopes.Value {
if r != nil && r.FindScope(k.Value) == nil {
for pair := orderedmap.First(l.Scopes.Value); pair != nil; pair = pair.Next() {
if r != nil && r.FindScope(pair.Key().Value) == nil {
CreateChange(&changes, ObjectRemoved, v3.Scopes,
v.ValueNode, nil, true,
k.Value, nil)
pair.Value().ValueNode, nil, true,
pair.Key().Value, nil)
continue
}
if r != nil && r.FindScope(k.Value) != nil {
if v.Value != r.FindScope(k.Value).Value {
if r != nil && r.FindScope(pair.Key().Value) != nil {
if pair.Value().Value != r.FindScope(pair.Key().Value).Value {
CreateChange(&changes, Modified, v3.Scopes,
v.ValueNode, r.FindScope(k.Value).ValueNode, true,
v.Value, r.FindScope(k.Value).Value)
pair.Value().ValueNode, r.FindScope(pair.Key().Value).ValueNode, true,
pair.Value().Value, r.FindScope(pair.Key().Value).Value)
}
}
}
for k, v := range r.Scopes.Value {
if l != nil && l.FindScope(k.Value) == nil {
for pair := orderedmap.First(r.Scopes.Value); pair != nil; pair = pair.Next() {
if l != nil && l.FindScope(pair.Key().Value) == nil {
CreateChange(&changes, ObjectAdded, v3.Scopes,
nil, v.ValueNode, false,
nil, k.Value)
nil, pair.Value().ValueNode, false,
nil, pair.Key().Value)
}
}
oa := new(OAuthFlowChanges)