mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-09 20:47:44 +00:00
v3 Links, callbacks operations low level models at 100% coverage
This commit is contained in:
@@ -38,7 +38,7 @@ func NewLink(link *low.Link) *Link {
|
|||||||
l.OperationRef = link.OperationRef.Value
|
l.OperationRef = link.OperationRef.Value
|
||||||
l.OperationId = link.OperationId.Value
|
l.OperationId = link.OperationId.Value
|
||||||
params := make(map[string]string)
|
params := make(map[string]string)
|
||||||
for k, v := range link.Parameters.Value {
|
for k, v := range link.Parameters {
|
||||||
params[k.Value] = v.Value
|
params[k.Value] = v.Value
|
||||||
}
|
}
|
||||||
l.Parameters = params
|
l.Parameters = params
|
||||||
|
|||||||
@@ -4,9 +4,12 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Callback represents a low-level Callback object for OpenAPI 3+.
|
// 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
|
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, "|")))
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)
|
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())
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -141,5 +141,4 @@ example: a thing`
|
|||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,16 +182,22 @@ func (o *Operation) Hash() [32]byte {
|
|||||||
for k := range o.Parameters.Value {
|
for k := range o.Parameters.Value {
|
||||||
keys[k] = low.GenerateHashString(o.Parameters.Value[k].Value)
|
keys[k] = low.GenerateHashString(o.Parameters.Value[k].Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
f = append(f, 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 {
|
for k := range o.Extensions {
|
||||||
f = append(f, fmt.Sprintf("%s-%x", k.Value,
|
f = append(f, fmt.Sprintf("%s-%x", k.Value,
|
||||||
sha256.Sum256([]byte(fmt.Sprint(o.Extensions[k].Value)))))
|
sha256.Sum256([]byte(fmt.Sprint(o.Extensions[k].Value)))))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add callbacks in here.
|
|
||||||
|
|
||||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
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]] {
|
func (o *Operation) GetTags() low.NodeReference[[]low.ValueReference[string]] {
|
||||||
return o.Tags
|
return o.Tags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) GetSummary() low.NodeReference[string] {
|
func (o *Operation) GetSummary() low.NodeReference[string] {
|
||||||
return o.Summary
|
return o.Summary
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) GetDescription() low.NodeReference[string] {
|
func (o *Operation) GetDescription() low.NodeReference[string] {
|
||||||
return o.Description
|
return o.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) GetExternalDocs() low.NodeReference[any] {
|
func (o *Operation) GetExternalDocs() low.NodeReference[any] {
|
||||||
return low.NodeReference[any]{
|
return low.NodeReference[any]{
|
||||||
ValueNode: o.ExternalDocs.ValueNode,
|
ValueNode: o.ExternalDocs.ValueNode,
|
||||||
@@ -216,19 +219,15 @@ func (o *Operation) GetExternalDocs() low.NodeReference[any] {
|
|||||||
Value: o.ExternalDocs.Value,
|
Value: o.ExternalDocs.Value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) GetOperationId() low.NodeReference[string] {
|
func (o *Operation) GetOperationId() low.NodeReference[string] {
|
||||||
return o.OperationId
|
return o.OperationId
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) GetDeprecated() low.NodeReference[bool] {
|
func (o *Operation) GetDeprecated() low.NodeReference[bool] {
|
||||||
return o.Deprecated
|
return o.Deprecated
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) GetExtensions() map[low.KeyReference[string]]low.ValueReference[any] {
|
func (o *Operation) GetExtensions() map[low.KeyReference[string]]low.ValueReference[any] {
|
||||||
return o.Extensions
|
return o.Extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) GetResponses() low.NodeReference[any] {
|
func (o *Operation) GetResponses() low.NodeReference[any] {
|
||||||
return low.NodeReference[any]{
|
return low.NodeReference[any]{
|
||||||
ValueNode: o.Responses.ValueNode,
|
ValueNode: o.Responses.ValueNode,
|
||||||
@@ -236,7 +235,6 @@ func (o *Operation) GetResponses() low.NodeReference[any] {
|
|||||||
Value: o.Responses.Value,
|
Value: o.Responses.Value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) GetParameters() low.NodeReference[any] {
|
func (o *Operation) GetParameters() low.NodeReference[any] {
|
||||||
return low.NodeReference[any]{
|
return low.NodeReference[any]{
|
||||||
ValueNode: o.Parameters.ValueNode,
|
ValueNode: o.Parameters.ValueNode,
|
||||||
@@ -244,7 +242,6 @@ func (o *Operation) GetParameters() low.NodeReference[any] {
|
|||||||
Value: o.Parameters.Value,
|
Value: o.Parameters.Value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) GetSecurity() low.NodeReference[any] {
|
func (o *Operation) GetSecurity() low.NodeReference[any] {
|
||||||
return low.NodeReference[any]{
|
return low.NodeReference[any]{
|
||||||
ValueNode: o.Security.ValueNode,
|
ValueNode: o.Security.ValueNode,
|
||||||
@@ -252,7 +249,6 @@ func (o *Operation) GetSecurity() low.NodeReference[any] {
|
|||||||
Value: o.Security.Value,
|
Value: o.Security.Value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) GetServers() low.NodeReference[any] {
|
func (o *Operation) GetServers() low.NodeReference[any] {
|
||||||
return low.NodeReference[any]{
|
return low.NodeReference[any]{
|
||||||
ValueNode: o.Servers.ValueNode,
|
ValueNode: o.Servers.ValueNode,
|
||||||
@@ -260,7 +256,6 @@ func (o *Operation) GetServers() low.NodeReference[any] {
|
|||||||
Value: o.Servers.Value,
|
Value: o.Servers.Value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (o *Operation) GetCallbacks() low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Callback]] {
|
||||||
//func (o *Operation) GetCallbacks() low.NodeReference[[]low.ValueReference[any]] {
|
return o.Callbacks
|
||||||
// return o.Produces
|
}
|
||||||
//}
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -191,3 +192,97 @@ func TestOperation_Build_FailServers(t *testing.T) {
|
|||||||
err = n.Build(idxNode.Content[0], idx)
|
err = n.Build(idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
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"))
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -109,11 +109,11 @@ func CompareLinks(l, r *v3.Link) *LinkChanges {
|
|||||||
// parameters
|
// parameters
|
||||||
lValues := make(map[string]low.ValueReference[string])
|
lValues := make(map[string]low.ValueReference[string])
|
||||||
rValues := make(map[string]low.ValueReference[string])
|
rValues := make(map[string]low.ValueReference[string])
|
||||||
for i := range l.Parameters.Value {
|
for i := range l.Parameters {
|
||||||
lValues[i.Value] = l.Parameters.Value[i]
|
lValues[i.Value] = l.Parameters[i]
|
||||||
}
|
}
|
||||||
for i := range r.Parameters.Value {
|
for i := range r.Parameters {
|
||||||
rValues[i.Value] = r.Parameters.Value[i]
|
rValues[i.Value] = r.Parameters[i]
|
||||||
}
|
}
|
||||||
for k := range lValues {
|
for k := range lValues {
|
||||||
if _, ok := rValues[k]; !ok {
|
if _, ok := rValues[k]; !ok {
|
||||||
|
|||||||
Reference in New Issue
Block a user