v3 Links, callbacks operations low level models at 100% coverage

This commit is contained in:
Dave Shanley
2022-11-09 09:26:23 -05:00
parent 4ca8e160ed
commit aa62232440
7 changed files with 172 additions and 24 deletions

View File

@@ -38,7 +38,7 @@ func NewLink(link *low.Link) *Link {
l.OperationRef = link.OperationRef.Value
l.OperationId = link.OperationId.Value
params := make(map[string]string)
for k, v := range link.Parameters.Value {
for k, v := range link.Parameters {
params[k.Value] = v.Value
}
l.Parameters = params

View File

@@ -4,9 +4,12 @@
package v3
import (
"crypto/sha256"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"gopkg.in/yaml.v3"
"sort"
"strings"
)
// Callback represents a low-level Callback object for OpenAPI 3+.
@@ -59,3 +62,18 @@ func (cb *Callback) Build(root *yaml.Node, idx *index.SpecIndex) error {
}
return nil
}
// Hash will return a consistent SHA256 Hash of the Callback object
func (cb *Callback) Hash() [32]byte {
var f []string
var keys []string
keys = make([]string, len(cb.Expression.Value))
z := 0
for k := range cb.Expression.Value {
keys[z] = low.GenerateHashString(cb.Expression.Value[k].Value)
z++
}
sort.Strings(keys)
f = append(f, keys...)
return sha256.Sum256([]byte(strings.Join(f, "|")))
}

View File

@@ -111,3 +111,44 @@ func TestCallback_Build_Using_InlineRef(t *testing.T) {
assert.Equal(t, "this is something", exp.Value.Post.Value.RequestBody.Value.Description.Value)
}
func TestCallback_Hash(t *testing.T) {
yml := `x-seed: grow
pizza:
description: cheesy
burgers:
description: tasty!
beer:
description: fantastic
x-weed: loved`
var idxNode yaml.Node
_ = yaml.Unmarshal([]byte(yml), &idxNode)
idx := index.NewSpecIndex(&idxNode)
var n Callback
_ = low.BuildModel(idxNode.Content[0], &n)
_ = n.Build(idxNode.Content[0], idx)
yml2 := `burgers:
description: tasty!
pizza:
description: cheesy
x-weed: loved
x-seed: grow
beer:
description: fantastic
`
var idxNode2 yaml.Node
_ = yaml.Unmarshal([]byte(yml2), &idxNode2)
idx2 := index.NewSpecIndex(&idxNode2)
var n2 Callback
_ = low.BuildModel(idxNode2.Content[0], &n2)
_ = n2.Build(idxNode2.Content[0], idx2)
// hash
assert.Equal(t, n.Hash(), n2.Hash())
}

View File

@@ -141,5 +141,4 @@ example: a thing`
// hash
assert.Equal(t, n.Hash(), n2.Hash())
}

View File

@@ -182,16 +182,22 @@ func (o *Operation) Hash() [32]byte {
for k := range o.Parameters.Value {
keys[k] = low.GenerateHashString(o.Parameters.Value[k].Value)
}
sort.Strings(keys)
f = append(f, keys...)
keys = make([]string, len(o.Callbacks.Value))
z := 0
for k := range o.Callbacks.Value {
keys[z] = low.GenerateHashString(o.Callbacks.Value[k].Value)
z++
}
sort.Strings(keys)
f = append(f, keys...)
for k := range o.Extensions {
f = append(f, fmt.Sprintf("%s-%x", k.Value,
sha256.Sum256([]byte(fmt.Sprint(o.Extensions[k].Value)))))
}
// TODO: add callbacks in here.
return sha256.Sum256([]byte(strings.Join(f, "|")))
}
@@ -200,15 +206,12 @@ func (o *Operation) Hash() [32]byte {
func (o *Operation) GetTags() low.NodeReference[[]low.ValueReference[string]] {
return o.Tags
}
func (o *Operation) GetSummary() low.NodeReference[string] {
return o.Summary
}
func (o *Operation) GetDescription() low.NodeReference[string] {
return o.Description
}
func (o *Operation) GetExternalDocs() low.NodeReference[any] {
return low.NodeReference[any]{
ValueNode: o.ExternalDocs.ValueNode,
@@ -216,19 +219,15 @@ func (o *Operation) GetExternalDocs() low.NodeReference[any] {
Value: o.ExternalDocs.Value,
}
}
func (o *Operation) GetOperationId() low.NodeReference[string] {
return o.OperationId
}
func (o *Operation) GetDeprecated() low.NodeReference[bool] {
return o.Deprecated
}
func (o *Operation) GetExtensions() map[low.KeyReference[string]]low.ValueReference[any] {
return o.Extensions
}
func (o *Operation) GetResponses() low.NodeReference[any] {
return low.NodeReference[any]{
ValueNode: o.Responses.ValueNode,
@@ -236,7 +235,6 @@ func (o *Operation) GetResponses() low.NodeReference[any] {
Value: o.Responses.Value,
}
}
func (o *Operation) GetParameters() low.NodeReference[any] {
return low.NodeReference[any]{
ValueNode: o.Parameters.ValueNode,
@@ -244,7 +242,6 @@ func (o *Operation) GetParameters() low.NodeReference[any] {
Value: o.Parameters.Value,
}
}
func (o *Operation) GetSecurity() low.NodeReference[any] {
return low.NodeReference[any]{
ValueNode: o.Security.ValueNode,
@@ -252,7 +249,6 @@ func (o *Operation) GetSecurity() low.NodeReference[any] {
Value: o.Security.Value,
}
}
func (o *Operation) GetServers() low.NodeReference[any] {
return low.NodeReference[any]{
ValueNode: o.Servers.ValueNode,
@@ -260,7 +256,6 @@ func (o *Operation) GetServers() low.NodeReference[any] {
Value: o.Servers.Value,
}
}
//func (o *Operation) GetCallbacks() low.NodeReference[[]low.ValueReference[any]] {
// return o.Produces
//}
func (o *Operation) GetCallbacks() low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Callback]] {
return o.Callbacks
}

View File

@@ -5,6 +5,7 @@ package v3
import (
"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"
@@ -191,3 +192,97 @@ func TestOperation_Build_FailServers(t *testing.T) {
err = n.Build(idxNode.Content[0], idx)
assert.Error(t, err)
}
func TestOperation_Hash_n_Grab(t *testing.T) {
yml := `tags:
- nice
- rice
summary: a thing
description: another thing
externalDocs:
url: https://pb33f.io/docs
operationId: sleepyMornings
parameters:
- name: parammy
in: my head
requestBody:
description: a thing
responses:
"200":
description: ok
callbacks:
callMe:
something: blue
deprecated: true
security:
- lego:
dont: stand
or: eat
servers:
- url: https://pb33f.io
x-mint: sweet`
var idxNode yaml.Node
_ = yaml.Unmarshal([]byte(yml), &idxNode)
idx := index.NewSpecIndex(&idxNode)
var n Operation
_ = low.BuildModel(idxNode.Content[0], &n)
_ = n.Build(idxNode.Content[0], idx)
yml2 := `tags:
- nice
- rice
summary: a thing
description: another thing
externalDocs:
url: https://pb33f.io/docs
operationId: sleepyMornings
parameters:
- name: parammy
in: my head
requestBody:
description: a thing
responses:
"200":
description: ok
callbacks:
callMe:
something: blue
deprecated: true
security:
- lego:
dont: stand
or: eat
servers:
- url: https://pb33f.io
x-mint: sweet`
var idxNode2 yaml.Node
_ = yaml.Unmarshal([]byte(yml2), &idxNode2)
idx2 := index.NewSpecIndex(&idxNode2)
var n2 Operation
_ = low.BuildModel(idxNode2.Content[0], &n2)
_ = n2.Build(idxNode2.Content[0], idx2)
// hash
assert.Equal(t, n.Hash(), n2.Hash())
// n grab
assert.Len(t, n.GetTags().Value, 2)
assert.Equal(t, "a thing", n.GetSummary().Value)
assert.Equal(t, "another thing", n.GetDescription().Value)
assert.Equal(t, "https://pb33f.io/docs", n.GetExternalDocs().Value.(*base.ExternalDoc).URL.Value)
assert.Equal(t, "sleepyMornings", n.GetOperationId().Value)
assert.Len(t, n.GetParameters().Value, 1)
assert.Len(t, n.GetSecurity().Value, 1)
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.Nil(t, n.FindSecurityRequirement("I do not exist"))
}

View File

@@ -109,11 +109,11 @@ func CompareLinks(l, r *v3.Link) *LinkChanges {
// parameters
lValues := make(map[string]low.ValueReference[string])
rValues := make(map[string]low.ValueReference[string])
for i := range l.Parameters.Value {
lValues[i.Value] = l.Parameters.Value[i]
for i := range l.Parameters {
lValues[i.Value] = l.Parameters[i]
}
for i := range r.Parameters.Value {
rValues[i.Value] = r.Parameters.Value[i]
for i := range r.Parameters {
rValues[i.Value] = r.Parameters[i]
}
for k := range lValues {
if _, ok := rValues[k]; !ok {