Building out model some more.

everything is holding up well.
This commit is contained in:
Dave Shanley
2022-07-31 16:15:01 -04:00
parent 2f60694047
commit a4012594de
13 changed files with 2061 additions and 1857 deletions

View File

@@ -8,10 +8,10 @@ type Document struct {
Version low.NodeReference[string]
Info low.NodeReference[*Info]
Servers []low.NodeReference[*Server]
Paths *Paths
Paths low.NodeReference[*Paths]
Components *Components
Security []*SecurityRequirement
Tags []low.NodeReference[*Tag]
ExternalDocs *ExternalDoc
Extensions map[string]low.ObjectReference
Extensions map[low.NodeReference[string]]low.NodeReference[any]
}

View File

@@ -1,36 +1,40 @@
package v3
import (
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/utils"
"gopkg.in/yaml.v3"
"sync"
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/utils"
"gopkg.in/yaml.v3"
"sync"
)
const (
InfoLabel = "info"
)
type Info struct {
Title low.NodeReference[string]
Description low.NodeReference[string]
TermsOfService low.NodeReference[string]
Contact low.NodeReference[*Contact]
License low.NodeReference[*License]
Version low.NodeReference[string]
Title low.NodeReference[string]
Description low.NodeReference[string]
TermsOfService low.NodeReference[string]
Contact low.NodeReference[*Contact]
License low.NodeReference[*License]
Version low.NodeReference[string]
}
func (i *Info) Build(root *yaml.Node) error {
var wg sync.WaitGroup
wg.Add(2)
var errs []error
var wg sync.WaitGroup
wg.Add(2)
var errs []error
contact := Contact{}
_, kln, cn := utils.FindKeyNodeFull("contact", root.Content)
go datamodel.BuildModelAsync(cn, &contact, &wg, &errs)
contact := Contact{}
_, kln, cn := utils.FindKeyNodeFull("contact", root.Content)
go datamodel.BuildModelAsync(cn, &contact, &wg, &errs)
license := License{}
_, kln, ln := utils.FindKeyNodeFull("license", root.Content)
go datamodel.BuildModelAsync(ln, &license, &wg, &errs)
wg.Wait()
i.Contact = low.NodeReference[*Contact]{Value: &contact, ValueNode: cn, KeyNode: kln}
i.License = low.NodeReference[*License]{Value: &license, ValueNode: ln, KeyNode: kln}
return nil
license := License{}
_, kln, ln := utils.FindKeyNodeFull("license", root.Content)
go datamodel.BuildModelAsync(ln, &license, &wg, &errs)
wg.Wait()
i.Contact = low.NodeReference[*Contact]{Value: &contact, ValueNode: cn, KeyNode: kln}
i.License = low.NodeReference[*License]{Value: &license, ValueNode: ln, KeyNode: kln}
return nil
}

View File

@@ -1,23 +1,79 @@
package v3
import (
"github.com/pb33f/libopenapi/datamodel/low"
"gopkg.in/yaml.v3"
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/utils"
"gopkg.in/yaml.v3"
)
const (
ParametersLabel = "parameters"
)
type Operation struct {
Node *yaml.Node
Tags []low.NodeReference[string]
Summary low.NodeReference[string]
Description low.NodeReference[string]
ExternalDocs ExternalDoc
OperationId low.NodeReference[string]
Parameters []Parameter
RequestBody RequestBody
Responses Responses
Callbacks map[string]Callback
Deprecated low.NodeReference[bool]
Security []SecurityRequirement
Servers []Server
Extensions map[string]low.ObjectReference
Tags []low.NodeReference[string]
Summary low.NodeReference[string]
Description low.NodeReference[string]
ExternalDocs *low.NodeReference[*ExternalDoc]
OperationId low.NodeReference[string]
Parameters []low.NodeReference[*Parameter]
RequestBody *low.NodeReference[*RequestBody]
Responses *low.NodeReference[*Responses]
Callbacks map[low.NodeReference[string]]low.NodeReference[*Callback]
Deprecated *low.NodeReference[bool]
Security []low.NodeReference[*SecurityRequirement]
Servers []low.NodeReference[*Server]
Extensions map[low.NodeReference[string]]low.NodeReference[any]
}
func (o *Operation) Build(root *yaml.Node, idx *index.SpecIndex) error {
extensionMap, err := datamodel.ExtractExtensions(root)
if err != nil {
return err
}
o.Extensions = extensionMap
// extract external docs
_, ln, exDocs := utils.FindKeyNodeFull(ExternalDocsLabel, root.Content)
if exDocs != nil {
var externalDoc ExternalDoc
err = datamodel.BuildModel(exDocs, &externalDoc)
if err != nil {
return err
}
o.ExternalDocs = &low.NodeReference[*ExternalDoc]{
Value: &externalDoc,
KeyNode: ln,
ValueNode: exDocs,
}
}
// build parameters
_, paramLabel, paramNode := utils.FindKeyNodeFull(ParametersLabel, root.Content)
if paramNode != nil && paramLabel != nil {
var params []low.NodeReference[*Parameter]
for _, pN := range paramNode.Content {
var param Parameter
err = datamodel.BuildModel(pN, &param)
if err != nil {
return err
}
err = param.Build(pN, idx)
if err != nil {
return err
}
params = append(params, low.NodeReference[*Parameter]{
Value: &param,
ValueNode: paramNode,
KeyNode: paramLabel,
})
}
}
return nil
}

View File

@@ -1,16 +1,38 @@
package v3
import (
"github.com/pb33f/libopenapi/datamodel/low"
"gopkg.in/yaml.v3"
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"gopkg.in/yaml.v3"
)
type Parameter struct {
Node *yaml.Node
Name low.NodeReference[string]
In low.NodeReference[string]
Description low.NodeReference[string]
Required low.NodeReference[bool]
Deprecated low.NodeReference[bool]
AllowEmptyValue low.NodeReference[bool]
Name low.NodeReference[string]
In low.NodeReference[string]
Description low.NodeReference[string]
Required low.NodeReference[bool]
Deprecated low.NodeReference[bool]
AllowEmptyValue low.NodeReference[bool]
Style low.NodeReference[string]
Explode low.NodeReference[bool]
AllowReserved low.NodeReference[bool]
Schema low.NodeReference[*Schema]
Example low.NodeReference[any]
Examples map[low.NodeReference[string]]low.NodeReference[*Example]
Extensions map[low.NodeReference[string]]low.NodeReference[any]
}
func (p *Parameter) Build(root *yaml.Node, idx *index.SpecIndex) error {
// extract extensions
extensionMap, err := datamodel.ExtractExtensions(root)
if err != nil {
return err
}
p.Extensions = extensionMap
// deal with schema
return nil
}

View File

@@ -1,30 +1,200 @@
package v3
import (
"github.com/pb33f/libopenapi/datamodel/low"
"gopkg.in/yaml.v3"
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"gopkg.in/yaml.v3"
"strings"
"sync"
)
const (
PathsLabel = "paths"
GetLabel = "get"
PostLabel = "post"
PatchLabel = "patch"
PutLabel = "put"
DeleteLabel = "delete"
OptionsLabel = "options"
HeadLabel = "head"
TraceLabel = "trace"
)
type Paths struct {
Node *yaml.Node
Paths map[string]Path
Extensions map[string]low.ObjectReference
Paths map[low.NodeReference[string]]low.NodeReference[*Path]
Extensions map[low.NodeReference[string]]low.NodeReference[any]
}
func (p *Paths) GetPathMap() map[string]*Path {
pMap := make(map[string]*Path)
for i, pv := range p.Paths {
pMap[i.Value] = pv.Value
}
return pMap
}
func (p *Paths) Build(root *yaml.Node, idx *index.SpecIndex) error {
// extract extensions
extensionMap, err := datamodel.ExtractExtensions(root)
if err != nil {
return err
}
p.Extensions = extensionMap
skip := false
var currentNode *yaml.Node
pathsMap := make(map[low.NodeReference[string]]low.NodeReference[*Path])
for i, pathNode := range root.Content {
if strings.HasPrefix(strings.ToLower(pathNode.Value), "x-") {
skip = true
continue
}
if skip {
skip = false
continue
}
if i%2 == 0 {
currentNode = pathNode
continue
}
var path = Path{}
err = datamodel.BuildModel(pathNode, &path)
if err != nil {
}
err = path.Build(pathNode, idx)
if err != nil {
return err
}
// add bulk here
pathsMap[low.NodeReference[string]{
Value: currentNode.Value,
KeyNode: currentNode,
}] = low.NodeReference[*Path]{
Value: &path,
ValueNode: pathNode,
}
}
p.Paths = pathsMap
return nil
}
type Path struct {
Node *yaml.Node
Value low.NodeReference[string]
Summary low.NodeReference[string]
Description low.NodeReference[string]
Get Operation
Put Operation
Post Operation
Delete Operation
Options Operation
Head Operation
Patch Operation
Trace Operation
Servers []Server
Parameters []Parameter
Extensions map[string]low.ObjectReference
Description low.NodeReference[string]
Summary low.NodeReference[string]
Get *low.NodeReference[*Operation]
Put *low.NodeReference[*Operation]
Post *low.NodeReference[*Operation]
Delete *low.NodeReference[*Operation]
Options *low.NodeReference[*Operation]
Head *low.NodeReference[*Operation]
Patch *low.NodeReference[*Operation]
Trace *low.NodeReference[*Operation]
Servers []*low.NodeReference[*Server]
Parameters []*low.NodeReference[*Parameter]
Extensions map[low.NodeReference[string]]low.NodeReference[any]
}
func (p *Path) Build(root *yaml.Node, idx *index.SpecIndex) error {
extensionMap, err := datamodel.ExtractExtensions(root)
if err != nil {
return err
}
p.Extensions = extensionMap
skip := false
var currentNode *yaml.Node
var wg sync.WaitGroup
var errors []error
var ops []low.NodeReference[*Operation]
for i, pathNode := range root.Content {
if strings.HasPrefix(strings.ToLower(pathNode.Value), "x-") {
skip = true
continue
}
if skip {
skip = false
continue
}
if i%2 == 0 {
currentNode = pathNode
continue
}
var op Operation
wg.Add(1)
datamodel.BuildModelAsync(pathNode, &op, &wg, &errors)
opRef := low.NodeReference[*Operation]{
Value: &op,
KeyNode: currentNode,
ValueNode: pathNode,
}
ops = append(ops, opRef)
switch currentNode.Value {
case GetLabel:
p.Get = &opRef
case PostLabel:
p.Post = &opRef
case PutLabel:
p.Put = &opRef
case PatchLabel:
p.Patch = &opRef
case DeleteLabel:
p.Delete = &opRef
case HeadLabel:
p.Head = &opRef
case OptionsLabel:
p.Options = &opRef
case TraceLabel:
p.Trace = &opRef
}
}
wg.Wait()
// all operations have been superficially built,
// now we need to build out the operation, we will do this asynchronously for speed.
opBuildChan := make(chan bool)
opErrorChan := make(chan error)
var buildOpFunc = func(op low.NodeReference[*Operation], ch chan<- bool, errCh chan<- error) {
// build out the operation.
er := op.Value.Build(op.ValueNode, idx)
if err != nil {
errCh <- er
}
ch <- true
}
for _, op := range ops {
go buildOpFunc(op, opBuildChan, opErrorChan)
}
n := 0
allDone:
for {
select {
case buildError := <-opErrorChan:
return buildError
case <-opBuildChan:
if n == len(ops)-1 {
break allDone
}
}
}
return nil
}

View File

@@ -8,7 +8,8 @@ import (
)
const (
Variables = "variables"
VariablesLabel = "variables"
ServersLabel = "servers"
)
type Server struct {
@@ -18,7 +19,7 @@ type Server struct {
}
func (s *Server) Build(root *yaml.Node) error {
kn, vars := utils.FindKeyNode(Variables, root.Content)
kn, vars := utils.FindKeyNode(VariablesLabel, root.Content)
if vars == nil {
return nil
}

View File

@@ -8,8 +8,8 @@ import (
)
const (
Tags = "tags"
ExternalDocs = "externalDocs"
TagsLabel = "tags"
ExternalDocsLabel = "externalDocs"
)
type Tag struct {
@@ -20,8 +20,6 @@ type Tag struct {
}
func (t *Tag) Build(root *yaml.Node) error {
_, ln, exDocs := utils.FindKeyNodeFull(ExternalDocs, root.Content)
// extract extensions
extensionMap, err := datamodel.ExtractExtensions(root)
if err != nil {
@@ -29,6 +27,7 @@ func (t *Tag) Build(root *yaml.Node) error {
}
t.Extensions = extensionMap
_, ln, exDocs := utils.FindKeyNodeFull(ExternalDocsLabel, root.Content)
// extract external docs
var externalDoc ExternalDoc
err = datamodel.BuildModel(exDocs, &externalDoc)

File diff suppressed because it is too large Load Diff

View File

@@ -1,274 +1,274 @@
package index
import (
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"io/ioutil"
"testing"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
"io/ioutil"
"testing"
)
func TestSpecIndex_ExtractRefsStripe(t *testing.T) {
stripe, _ := ioutil.ReadFile("../test_specs/stripe.yaml")
var rootNode yaml.Node
yaml.Unmarshal(stripe, &rootNode)
stripe, _ := ioutil.ReadFile("../test_specs/stripe.yaml")
var rootNode yaml.Node
yaml.Unmarshal(stripe, &rootNode)
index := NewSpecIndex(&rootNode)
index := NewSpecIndex(&rootNode)
assert.Len(t, index.allRefs, 385)
assert.Len(t, index.allMappedRefs, 385)
assert.Len(t, index.allRefs, 385)
assert.Len(t, index.allMappedRefs, 385)
combined := index.GetAllCombinedReferences()
assert.Equal(t, 537, len(combined))
combined := index.GetAllCombinedReferences()
assert.Equal(t, 537, len(combined))
assert.Len(t, index.rawSequencedRefs, 1972)
assert.Equal(t, 246, index.pathCount)
assert.Equal(t, 402, index.operationCount)
assert.Equal(t, 537, index.schemaCount)
assert.Equal(t, 0, index.globalTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Equal(t, 0, index.componentParamCount)
assert.Equal(t, 143, index.operationParamCount)
assert.Equal(t, 88, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 55, index.componentsInlineParamUniqueCount)
assert.Equal(t, 1516, index.enumCount)
assert.Len(t, index.GetAllEnums(), 1516)
assert.Len(t, index.GetPolyAllOfReferences(), 0)
assert.Len(t, index.GetPolyOneOfReferences(), 275)
assert.Len(t, index.GetPolyAnyOfReferences(), 553)
assert.NotNil(t, index.GetRootServersNode())
assert.Len(t, index.GetAllRootServers(), 1)
assert.Len(t, index.rawSequencedRefs, 1972)
assert.Equal(t, 246, index.pathCount)
assert.Equal(t, 402, index.operationCount)
assert.Equal(t, 537, index.schemaCount)
assert.Equal(t, 0, index.globalTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Equal(t, 0, index.componentParamCount)
assert.Equal(t, 143, index.operationParamCount)
assert.Equal(t, 88, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 55, index.componentsInlineParamUniqueCount)
assert.Equal(t, 1516, index.enumCount)
assert.Len(t, index.GetAllEnums(), 1516)
assert.Len(t, index.GetPolyAllOfReferences(), 0)
assert.Len(t, index.GetPolyOneOfReferences(), 275)
assert.Len(t, index.GetPolyAnyOfReferences(), 553)
assert.NotNil(t, index.GetRootServersNode())
assert.Len(t, index.GetAllRootServers(), 1)
}
func TestSpecIndex_Asana(t *testing.T) {
asana, _ := ioutil.ReadFile("../test_specs/asana.yaml")
var rootNode yaml.Node
yaml.Unmarshal(asana, &rootNode)
asana, _ := ioutil.ReadFile("../test_specs/asana.yaml")
var rootNode yaml.Node
yaml.Unmarshal(asana, &rootNode)
index := NewSpecIndex(&rootNode)
index := NewSpecIndex(&rootNode)
assert.Len(t, index.allRefs, 152)
assert.Len(t, index.allMappedRefs, 152)
combined := index.GetAllCombinedReferences()
assert.Equal(t, 171, len(combined))
assert.Equal(t, 118, index.pathCount)
assert.Equal(t, 152, index.operationCount)
assert.Equal(t, 135, index.schemaCount)
assert.Equal(t, 26, index.globalTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Equal(t, 30, index.componentParamCount)
assert.Equal(t, 107, index.operationParamCount)
assert.Equal(t, 8, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 69, index.componentsInlineParamUniqueCount)
assert.Len(t, index.allRefs, 152)
assert.Len(t, index.allMappedRefs, 152)
combined := index.GetAllCombinedReferences()
assert.Equal(t, 171, len(combined))
assert.Equal(t, 118, index.pathCount)
assert.Equal(t, 152, index.operationCount)
assert.Equal(t, 135, index.schemaCount)
assert.Equal(t, 26, index.globalTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Equal(t, 30, index.componentParamCount)
assert.Equal(t, 107, index.operationParamCount)
assert.Equal(t, 8, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 69, index.componentsInlineParamUniqueCount)
}
func TestSpecIndex_k8s(t *testing.T) {
asana, _ := ioutil.ReadFile("../test_specs/k8s.json")
var rootNode yaml.Node
yaml.Unmarshal(asana, &rootNode)
asana, _ := ioutil.ReadFile("../test_specs/k8s.json")
var rootNode yaml.Node
yaml.Unmarshal(asana, &rootNode)
index := NewSpecIndex(&rootNode)
index := NewSpecIndex(&rootNode)
assert.Len(t, index.allRefs, 558)
assert.Len(t, index.allMappedRefs, 558)
combined := index.GetAllCombinedReferences()
assert.Equal(t, 563, len(combined))
assert.Equal(t, 436, index.pathCount)
assert.Equal(t, 853, index.operationCount)
assert.Equal(t, 563, index.schemaCount)
assert.Equal(t, 0, index.globalTagsCount)
assert.Equal(t, 58, index.operationTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Equal(t, 0, index.componentParamCount)
assert.Equal(t, 36, index.operationParamCount)
assert.Equal(t, 26, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 10, index.componentsInlineParamUniqueCount)
assert.Equal(t, 58, index.GetTotalTagsCount())
assert.Equal(t, 2524, index.GetRawReferenceCount())
assert.Len(t, index.allRefs, 558)
assert.Len(t, index.allMappedRefs, 558)
combined := index.GetAllCombinedReferences()
assert.Equal(t, 563, len(combined))
assert.Equal(t, 436, index.pathCount)
assert.Equal(t, 853, index.operationCount)
assert.Equal(t, 563, index.schemaCount)
assert.Equal(t, 0, index.globalTagsCount)
assert.Equal(t, 58, index.operationTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Equal(t, 0, index.componentParamCount)
assert.Equal(t, 36, index.operationParamCount)
assert.Equal(t, 26, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 10, index.componentsInlineParamUniqueCount)
assert.Equal(t, 58, index.GetTotalTagsCount())
assert.Equal(t, 2524, index.GetRawReferenceCount())
}
func TestSpecIndex_PetstoreV2(t *testing.T) {
asana, _ := ioutil.ReadFile("../test_specs/petstorev2.json")
var rootNode yaml.Node
yaml.Unmarshal(asana, &rootNode)
asana, _ := ioutil.ReadFile("../test_specs/petstorev2.json")
var rootNode yaml.Node
yaml.Unmarshal(asana, &rootNode)
index := NewSpecIndex(&rootNode)
index := NewSpecIndex(&rootNode)
assert.Len(t, index.allRefs, 6)
assert.Len(t, index.allMappedRefs, 6)
assert.Equal(t, 14, index.pathCount)
assert.Equal(t, 20, index.operationCount)
assert.Equal(t, 6, index.schemaCount)
assert.Equal(t, 3, index.globalTagsCount)
assert.Equal(t, 3, index.operationTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Equal(t, 1, index.componentParamCount)
assert.Equal(t, 1, index.GetComponentParameterCount())
assert.Equal(t, 11, index.operationParamCount)
assert.Equal(t, 5, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 6, index.componentsInlineParamUniqueCount)
assert.Equal(t, 3, index.GetTotalTagsCount())
assert.Len(t, index.allRefs, 6)
assert.Len(t, index.allMappedRefs, 6)
assert.Equal(t, 14, index.pathCount)
assert.Equal(t, 20, index.operationCount)
assert.Equal(t, 6, index.schemaCount)
assert.Equal(t, 3, index.globalTagsCount)
assert.Equal(t, 3, index.operationTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Equal(t, 1, index.componentParamCount)
assert.Equal(t, 1, index.GetComponentParameterCount())
assert.Equal(t, 11, index.operationParamCount)
assert.Equal(t, 5, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 6, index.componentsInlineParamUniqueCount)
assert.Equal(t, 3, index.GetTotalTagsCount())
}
func TestSpecIndex_XSOAR(t *testing.T) {
xsoar, _ := ioutil.ReadFile("../test_specs/xsoar.json")
var rootNode yaml.Node
yaml.Unmarshal(xsoar, &rootNode)
xsoar, _ := ioutil.ReadFile("../test_specs/xsoar.json")
var rootNode yaml.Node
yaml.Unmarshal(xsoar, &rootNode)
index := NewSpecIndex(&rootNode)
assert.Len(t, index.allRefs, 209)
assert.Equal(t, 85, index.pathCount)
assert.Equal(t, 88, index.operationCount)
assert.Equal(t, 245, index.schemaCount)
assert.Equal(t, 207, len(index.allMappedRefs))
assert.Equal(t, 0, index.globalTagsCount)
assert.Equal(t, 0, index.operationTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Len(t, index.GetRootSecurityReferences(), 1)
assert.NotNil(t, index.GetRootSecurityNode())
index := NewSpecIndex(&rootNode)
assert.Len(t, index.allRefs, 209)
assert.Equal(t, 85, index.pathCount)
assert.Equal(t, 88, index.operationCount)
assert.Equal(t, 245, index.schemaCount)
assert.Equal(t, 207, len(index.allMappedRefs))
assert.Equal(t, 0, index.globalTagsCount)
assert.Equal(t, 0, index.operationTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Len(t, index.GetRootSecurityReferences(), 1)
assert.NotNil(t, index.GetRootSecurityNode())
}
func TestSpecIndex_PetstoreV3(t *testing.T) {
asana, _ := ioutil.ReadFile("../test_specs/petstorev3.json")
var rootNode yaml.Node
yaml.Unmarshal(asana, &rootNode)
asana, _ := ioutil.ReadFile("../test_specs/petstorev3.json")
var rootNode yaml.Node
yaml.Unmarshal(asana, &rootNode)
index := NewSpecIndex(&rootNode)
index := NewSpecIndex(&rootNode)
assert.Len(t, index.allRefs, 7)
assert.Len(t, index.allMappedRefs, 7)
assert.Equal(t, 13, index.pathCount)
assert.Equal(t, 19, index.operationCount)
assert.Equal(t, 8, index.schemaCount)
assert.Equal(t, 3, index.globalTagsCount)
assert.Equal(t, 3, index.operationTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Equal(t, 0, index.componentParamCount)
assert.Equal(t, 9, index.operationParamCount)
assert.Equal(t, 4, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 5, index.componentsInlineParamUniqueCount)
assert.Equal(t, 3, index.GetTotalTagsCount())
assert.Equal(t, 90, index.GetAllDescriptionsCount())
assert.Equal(t, 19, index.GetAllSummariesCount())
assert.Len(t, index.GetAllDescriptions(), 90)
assert.Len(t, index.GetAllSummaries(), 19)
assert.Len(t, index.allRefs, 7)
assert.Len(t, index.allMappedRefs, 7)
assert.Equal(t, 13, index.pathCount)
assert.Equal(t, 19, index.operationCount)
assert.Equal(t, 8, index.schemaCount)
assert.Equal(t, 3, index.globalTagsCount)
assert.Equal(t, 3, index.operationTagsCount)
assert.Equal(t, 0, index.globalLinksCount)
assert.Equal(t, 0, index.componentParamCount)
assert.Equal(t, 9, index.operationParamCount)
assert.Equal(t, 4, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 5, index.componentsInlineParamUniqueCount)
assert.Equal(t, 3, index.GetTotalTagsCount())
assert.Equal(t, 90, index.GetAllDescriptionsCount())
assert.Equal(t, 19, index.GetAllSummariesCount())
assert.Len(t, index.GetAllDescriptions(), 90)
assert.Len(t, index.GetAllSummaries(), 19)
}
func TestSpecIndex_BurgerShop(t *testing.T) {
burgershop, _ := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
var rootNode yaml.Node
yaml.Unmarshal(burgershop, &rootNode)
burgershop, _ := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
var rootNode yaml.Node
yaml.Unmarshal(burgershop, &rootNode)
index := NewSpecIndex(&rootNode)
index := NewSpecIndex(&rootNode)
assert.Len(t, index.allRefs, 5)
assert.Len(t, index.allMappedRefs, 5)
assert.Equal(t, 5, len(index.GetMappedReferences()))
assert.Equal(t, 5, len(index.GetMappedReferencesSequenced()))
assert.Len(t, index.allRefs, 6)
assert.Len(t, index.allMappedRefs, 6)
assert.Equal(t, 6, len(index.GetMappedReferences()))
assert.Equal(t, 6, len(index.GetMappedReferencesSequenced()))
assert.Equal(t, 5, index.pathCount)
assert.Equal(t, 5, index.GetPathCount())
assert.Equal(t, 7, index.pathCount)
assert.Equal(t, 7, index.GetPathCount())
assert.Equal(t, 5, len(index.GetAllSchemas()))
assert.Equal(t, 5, len(index.GetAllSchemas()))
assert.Equal(t, 18, len(index.GetAllSequencedReferences()))
assert.NotNil(t, index.GetSchemasNode())
assert.Nil(t, index.GetParametersNode())
assert.Equal(t, 19, len(index.GetAllSequencedReferences()))
assert.NotNil(t, index.GetSchemasNode())
assert.Nil(t, index.GetParametersNode())
assert.Equal(t, 5, index.operationCount)
assert.Equal(t, 5, index.GetOperationCount())
assert.Equal(t, 5, index.operationCount)
assert.Equal(t, 5, index.GetOperationCount())
assert.Equal(t, 5, index.schemaCount)
assert.Equal(t, 5, index.GetComponentSchemaCount())
assert.Equal(t, 5, index.schemaCount)
assert.Equal(t, 5, index.GetComponentSchemaCount())
assert.Equal(t, 2, index.globalTagsCount)
assert.Equal(t, 2, index.GetGlobalTagsCount())
assert.Equal(t, 2, index.GetTotalTagsCount())
assert.Equal(t, 2, index.globalTagsCount)
assert.Equal(t, 2, index.GetGlobalTagsCount())
assert.Equal(t, 2, index.GetTotalTagsCount())
assert.Equal(t, 2, index.operationTagsCount)
assert.Equal(t, 2, index.GetOperationTagsCount())
assert.Equal(t, 2, index.operationTagsCount)
assert.Equal(t, 2, index.GetOperationTagsCount())
assert.Equal(t, 3, index.globalLinksCount)
assert.Equal(t, 3, index.GetGlobalLinksCount())
assert.Equal(t, 3, index.globalLinksCount)
assert.Equal(t, 3, index.GetGlobalLinksCount())
assert.Equal(t, 0, index.componentParamCount)
assert.Equal(t, 0, index.GetComponentParameterCount())
assert.Equal(t, 0, index.componentParamCount)
assert.Equal(t, 0, index.GetComponentParameterCount())
assert.Equal(t, 2, index.operationParamCount)
assert.Equal(t, 2, index.GetOperationsParameterCount())
assert.Equal(t, 2, index.operationParamCount)
assert.Equal(t, 2, index.GetOperationsParameterCount())
assert.Equal(t, 1, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 1, index.GetInlineDuplicateParamCount())
assert.Equal(t, 1, index.componentsInlineParamDuplicateCount)
assert.Equal(t, 1, index.GetInlineDuplicateParamCount())
assert.Equal(t, 1, index.componentsInlineParamUniqueCount)
assert.Equal(t, 1, index.GetInlineUniqueParamCount())
assert.Equal(t, 1, index.componentsInlineParamUniqueCount)
assert.Equal(t, 1, index.GetInlineUniqueParamCount())
assert.Equal(t, 0, len(index.GetAllRequestBodies()))
assert.NotNil(t, index.GetRootNode())
assert.NotNil(t, index.GetGlobalTagsNode())
assert.NotNil(t, index.GetPathsNode())
assert.NotNil(t, index.GetDiscoveredReferences())
assert.Equal(t, 0, len(index.GetPolyReferences()))
assert.NotNil(t, index.GetOperationParameterReferences())
assert.Equal(t, 0, len(index.GetAllSecuritySchemes()))
assert.Equal(t, 0, len(index.GetAllParameters()))
assert.Equal(t, 0, len(index.GetAllResponses()))
assert.Equal(t, 2, len(index.GetInlineOperationDuplicateParameters()))
assert.Equal(t, 0, len(index.GetReferencesWithSiblings()))
assert.Equal(t, 5, len(index.GetAllReferences()))
assert.Equal(t, 0, len(index.GetOperationParametersIndexErrors()))
assert.Equal(t, 5, len(index.GetAllPaths()))
assert.Equal(t, 5, len(index.GetOperationTags()))
assert.Equal(t, 3, len(index.GetAllParametersFromOperations()))
assert.Equal(t, 0, len(index.GetAllRequestBodies()))
assert.NotNil(t, index.GetRootNode())
assert.NotNil(t, index.GetGlobalTagsNode())
assert.NotNil(t, index.GetPathsNode())
assert.NotNil(t, index.GetDiscoveredReferences())
assert.Equal(t, 0, len(index.GetPolyReferences()))
assert.NotNil(t, index.GetOperationParameterReferences())
assert.Equal(t, 0, len(index.GetAllSecuritySchemes()))
assert.Equal(t, 0, len(index.GetAllParameters()))
assert.Equal(t, 0, len(index.GetAllResponses()))
assert.Equal(t, 2, len(index.GetInlineOperationDuplicateParameters()))
assert.Equal(t, 0, len(index.GetReferencesWithSiblings()))
assert.Equal(t, 6, len(index.GetAllReferences()))
assert.Equal(t, 0, len(index.GetOperationParametersIndexErrors()))
assert.Equal(t, 5, len(index.GetAllPaths()))
assert.Equal(t, 5, len(index.GetOperationTags()))
assert.Equal(t, 3, len(index.GetAllParametersFromOperations()))
}
func TestSpecIndex_BurgerShop_AllTheComponents(t *testing.T) {
burgershop, _ := ioutil.ReadFile("../test_specs/all-the-components.yaml")
var rootNode yaml.Node
yaml.Unmarshal(burgershop, &rootNode)
burgershop, _ := ioutil.ReadFile("../test_specs/all-the-components.yaml")
var rootNode yaml.Node
yaml.Unmarshal(burgershop, &rootNode)
index := NewSpecIndex(&rootNode)
index := NewSpecIndex(&rootNode)
assert.Equal(t, 1, len(index.GetAllHeaders()))
assert.Equal(t, 1, len(index.GetAllLinks()))
assert.Equal(t, 1, len(index.GetAllCallbacks()))
assert.Equal(t, 1, len(index.GetAllExamples()))
assert.Equal(t, 1, len(index.GetAllResponses()))
assert.Equal(t, 2, len(index.GetAllRootServers()))
assert.Equal(t, 2, len(index.GetAllOperationsServers()))
assert.Equal(t, 1, len(index.GetAllHeaders()))
assert.Equal(t, 1, len(index.GetAllLinks()))
assert.Equal(t, 1, len(index.GetAllCallbacks()))
assert.Equal(t, 1, len(index.GetAllExamples()))
assert.Equal(t, 1, len(index.GetAllResponses()))
assert.Equal(t, 2, len(index.GetAllRootServers()))
assert.Equal(t, 2, len(index.GetAllOperationsServers()))
}
func TestSpecIndex_SwaggerResponses(t *testing.T) {
yml := `swagger: 2.0
yml := `swagger: 2.0
responses:
niceResponse:
description: hi`
var rootNode yaml.Node
yaml.Unmarshal([]byte(yml), &rootNode)
var rootNode yaml.Node
yaml.Unmarshal([]byte(yml), &rootNode)
index := NewSpecIndex(&rootNode)
index := NewSpecIndex(&rootNode)
assert.Equal(t, 1, len(index.GetAllResponses()))
assert.Equal(t, 1, len(index.GetAllResponses()))
}
func TestSpecIndex_NoNameParam(t *testing.T) {
yml := `paths:
yml := `paths:
/users/{id}:
parameters:
- in: path
@@ -280,77 +280,77 @@ func TestSpecIndex_NoNameParam(t *testing.T) {
name: id
- in: query`
var rootNode yaml.Node
yaml.Unmarshal([]byte(yml), &rootNode)
var rootNode yaml.Node
yaml.Unmarshal([]byte(yml), &rootNode)
index := NewSpecIndex(&rootNode)
index := NewSpecIndex(&rootNode)
assert.Equal(t, 2, len(index.GetOperationParametersIndexErrors()))
assert.Equal(t, 2, len(index.GetOperationParametersIndexErrors()))
}
func TestSpecIndex_NoRoot(t *testing.T) {
index := NewSpecIndex(nil)
refs := index.ExtractRefs(nil, nil, nil, 0, false, "")
docs := index.ExtractExternalDocuments(nil)
assert.Nil(t, docs)
assert.Nil(t, refs)
assert.Nil(t, index.FindComponent("nothing", nil))
assert.Equal(t, -1, index.GetOperationCount())
assert.Equal(t, -1, index.GetPathCount())
assert.Equal(t, -1, index.GetGlobalTagsCount())
assert.Equal(t, -1, index.GetOperationTagsCount())
assert.Equal(t, -1, index.GetTotalTagsCount())
assert.Equal(t, -1, index.GetOperationsParameterCount())
assert.Equal(t, -1, index.GetComponentParameterCount())
assert.Equal(t, -1, index.GetComponentSchemaCount())
assert.Equal(t, -1, index.GetGlobalLinksCount())
index := NewSpecIndex(nil)
refs := index.ExtractRefs(nil, nil, nil, 0, false, "")
docs := index.ExtractExternalDocuments(nil)
assert.Nil(t, docs)
assert.Nil(t, refs)
assert.Nil(t, index.FindComponent("nothing", nil))
assert.Equal(t, -1, index.GetOperationCount())
assert.Equal(t, -1, index.GetPathCount())
assert.Equal(t, -1, index.GetGlobalTagsCount())
assert.Equal(t, -1, index.GetOperationTagsCount())
assert.Equal(t, -1, index.GetTotalTagsCount())
assert.Equal(t, -1, index.GetOperationsParameterCount())
assert.Equal(t, -1, index.GetComponentParameterCount())
assert.Equal(t, -1, index.GetComponentSchemaCount())
assert.Equal(t, -1, index.GetGlobalLinksCount())
}
func TestSpecIndex_BurgerShopMixedRef(t *testing.T) {
spec, _ := ioutil.ReadFile("../test_specs/mixedref-burgershop.openapi.yaml")
var rootNode yaml.Node
yaml.Unmarshal(spec, &rootNode)
spec, _ := ioutil.ReadFile("../test_specs/mixedref-burgershop.openapi.yaml")
var rootNode yaml.Node
yaml.Unmarshal(spec, &rootNode)
index := NewSpecIndex(&rootNode)
index := NewSpecIndex(&rootNode)
assert.Len(t, index.allRefs, 4)
assert.Len(t, index.allMappedRefs, 4)
assert.Equal(t, 5, index.GetPathCount())
assert.Equal(t, 5, index.GetOperationCount())
assert.Equal(t, 1, index.GetComponentSchemaCount())
assert.Equal(t, 2, index.GetGlobalTagsCount())
assert.Equal(t, 3, index.GetTotalTagsCount())
assert.Equal(t, 2, index.GetOperationTagsCount())
assert.Equal(t, 0, index.GetGlobalLinksCount())
assert.Equal(t, 0, index.GetComponentParameterCount())
assert.Equal(t, 2, index.GetOperationsParameterCount())
assert.Equal(t, 1, index.GetInlineDuplicateParamCount())
assert.Equal(t, 1, index.GetInlineUniqueParamCount())
assert.Len(t, index.allRefs, 4)
assert.Len(t, index.allMappedRefs, 4)
assert.Equal(t, 5, index.GetPathCount())
assert.Equal(t, 5, index.GetOperationCount())
assert.Equal(t, 1, index.GetComponentSchemaCount())
assert.Equal(t, 2, index.GetGlobalTagsCount())
assert.Equal(t, 3, index.GetTotalTagsCount())
assert.Equal(t, 2, index.GetOperationTagsCount())
assert.Equal(t, 0, index.GetGlobalLinksCount())
assert.Equal(t, 0, index.GetComponentParameterCount())
assert.Equal(t, 2, index.GetOperationsParameterCount())
assert.Equal(t, 1, index.GetInlineDuplicateParamCount())
assert.Equal(t, 1, index.GetInlineUniqueParamCount())
}
func TestSpecIndex_TestEmptyBrokenReferences(t *testing.T) {
asana, _ := ioutil.ReadFile("../test_specs/badref-burgershop.openapi.yaml")
var rootNode yaml.Node
yaml.Unmarshal(asana, &rootNode)
asana, _ := ioutil.ReadFile("../test_specs/badref-burgershop.openapi.yaml")
var rootNode yaml.Node
yaml.Unmarshal(asana, &rootNode)
index := NewSpecIndex(&rootNode)
assert.Equal(t, 5, index.GetPathCount())
assert.Equal(t, 5, index.GetOperationCount())
assert.Equal(t, 5, index.GetComponentSchemaCount())
assert.Equal(t, 2, index.GetGlobalTagsCount())
assert.Equal(t, 3, index.GetTotalTagsCount())
assert.Equal(t, 2, index.GetOperationTagsCount())
assert.Equal(t, 2, index.GetGlobalLinksCount())
assert.Equal(t, 0, index.GetComponentParameterCount())
assert.Equal(t, 2, index.GetOperationsParameterCount())
assert.Equal(t, 1, index.GetInlineDuplicateParamCount())
assert.Equal(t, 1, index.GetInlineUniqueParamCount())
assert.Len(t, index.refErrors, 7)
index := NewSpecIndex(&rootNode)
assert.Equal(t, 5, index.GetPathCount())
assert.Equal(t, 5, index.GetOperationCount())
assert.Equal(t, 5, index.GetComponentSchemaCount())
assert.Equal(t, 2, index.GetGlobalTagsCount())
assert.Equal(t, 3, index.GetTotalTagsCount())
assert.Equal(t, 2, index.GetOperationTagsCount())
assert.Equal(t, 2, index.GetGlobalLinksCount())
assert.Equal(t, 0, index.GetComponentParameterCount())
assert.Equal(t, 2, index.GetOperationsParameterCount())
assert.Equal(t, 1, index.GetInlineDuplicateParamCount())
assert.Equal(t, 1, index.GetInlineUniqueParamCount())
assert.Len(t, index.refErrors, 7)
}

View File

@@ -1,57 +1,63 @@
package openapi
import (
"fmt"
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/datamodel/low"
v3 "github.com/pb33f/libopenapi/datamodel/low/3.0"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/resolver"
"github.com/pb33f/libopenapi/utils"
"gopkg.in/yaml.v3"
"strconv"
"sync"
)
const (
Info = "info"
Servers = "servers"
)
func CreateDocument(info *datamodel.SpecInfo) (*v3.Document, error) {
doc := v3.Document{Version: low.NodeReference[string]{Value: info.Version, ValueNode: info.RootNode}}
// build an index
//idx := index.NewSpecIndex(info.RootNode)
//datamodel.BuildModel(info.RootNode.Content[0], &doc)
idx := index.NewSpecIndex(info.RootNode)
rsolvr := resolver.NewResolver(idx)
// todo handle errors
rsolvr.Resolve()
var wg sync.WaitGroup
var errors []error
var runExtraction = func(info *datamodel.SpecInfo, doc *v3.Document,
runFunc func(i *datamodel.SpecInfo, d *v3.Document) error,
runFunc func(i *datamodel.SpecInfo, d *v3.Document, idx *index.SpecIndex) error,
ers *[]error,
wg *sync.WaitGroup) {
if er := runFunc(info, doc); er != nil {
if er := runFunc(info, doc, idx); er != nil {
*ers = append(*ers, er)
}
wg.Done()
}
wg.Add(3)
go runExtraction(info, &doc, extractInfo, &errors, &wg)
go runExtraction(info, &doc, extractServers, &errors, &wg)
go runExtraction(info, &doc, extractTags, &errors, &wg)
extractionFuncs := []func(i *datamodel.SpecInfo, d *v3.Document, idx *index.SpecIndex) error{
extractInfo,
extractServers,
extractTags,
extractPaths,
}
wg.Add(len(extractionFuncs))
for _, f := range extractionFuncs {
go runExtraction(info, &doc, f, &errors, &wg)
}
wg.Wait()
// todo fix this.
if len(errors) > 0 {
return &doc, errors[0]
}
fmt.Sprint(idx)
return &doc, nil
}
func extractInfo(info *datamodel.SpecInfo, doc *v3.Document) error {
_, ln, vn := utils.FindKeyNodeFull(Info, info.RootNode.Content)
func extractInfo(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
_, ln, vn := utils.FindKeyNodeFull(v3.InfoLabel, info.RootNode.Content)
if vn != nil {
ir := v3.Info{}
err := datamodel.BuildModel(vn, &ir)
@@ -65,8 +71,8 @@ func extractInfo(info *datamodel.SpecInfo, doc *v3.Document) error {
return nil
}
func extractServers(info *datamodel.SpecInfo, doc *v3.Document) error {
_, ln, vn := utils.FindKeyNodeFull(Servers, info.RootNode.Content)
func extractServers(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
_, ln, vn := utils.FindKeyNodeFull(v3.ServersLabel, info.RootNode.Content)
if vn != nil {
if utils.IsNodeArray(vn) {
var servers []low.NodeReference[*v3.Server]
@@ -91,8 +97,8 @@ func extractServers(info *datamodel.SpecInfo, doc *v3.Document) error {
return nil
}
func extractTags(info *datamodel.SpecInfo, doc *v3.Document) error {
_, ln, vn := utils.FindKeyNodeFull(v3.Tags, info.RootNode.Content)
func extractTags(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
_, ln, vn := utils.FindKeyNodeFull(v3.TagsLabel, info.RootNode.Content)
if vn != nil {
if utils.IsNodeArray(vn) {
var tags []low.NodeReference[*v3.Tag]
@@ -117,66 +123,16 @@ func extractTags(info *datamodel.SpecInfo, doc *v3.Document) error {
return nil
}
func ExtractExtensions(root *yaml.Node) (map[low.NodeReference[string]]low.NodeReference[any], error) {
extensions := utils.FindExtensionNodes(root.Content)
extensionMap := make(map[low.NodeReference[string]]low.NodeReference[any])
for _, ext := range extensions {
// this is an object, decode into an unknown map.
if utils.IsNodeMap(ext.Value) {
var v interface{}
err := ext.Value.Decode(&v)
if err != nil {
return nil, err
}
extensionMap[low.NodeReference[string]{
Value: ext.Key.Value,
KeyNode: ext.Key,
ValueNode: ext.Value,
}] = low.NodeReference[any]{Value: v, KeyNode: ext.Key}
}
if utils.IsNodeStringValue(ext.Value) {
extensionMap[low.NodeReference[string]{
Value: ext.Key.Value,
KeyNode: ext.Key,
ValueNode: ext.Value,
}] = low.NodeReference[any]{Value: ext.Value.Value, ValueNode: ext.Value}
}
if utils.IsNodeFloatValue(ext.Value) {
fv, _ := strconv.ParseFloat(ext.Value.Value, 64)
extensionMap[low.NodeReference[string]{
Value: ext.Key.Value,
KeyNode: ext.Key,
ValueNode: ext.Value,
}] = low.NodeReference[any]{Value: fv, ValueNode: ext.Value}
}
if utils.IsNodeIntValue(ext.Value) {
iv, _ := strconv.ParseInt(ext.Value.Value, 10, 64)
extensionMap[low.NodeReference[string]{
Value: ext.Key.Value,
KeyNode: ext.Key,
ValueNode: ext.Value,
}] = low.NodeReference[any]{Value: iv, ValueNode: ext.Value}
}
if utils.IsNodeBoolValue(ext.Value) {
bv, _ := strconv.ParseBool(ext.Value.Value)
extensionMap[low.NodeReference[string]{
Value: ext.Key.Value,
KeyNode: ext.Key,
ValueNode: ext.Value,
}] = low.NodeReference[any]{Value: bv, ValueNode: ext.Value}
}
if utils.IsNodeArray(ext.Value) {
var v []interface{}
err := ext.Value.Decode(&v)
if err != nil {
return nil, err
}
extensionMap[low.NodeReference[string]{
Value: ext.Key.Value,
KeyNode: ext.Key,
ValueNode: ext.Value,
}] = low.NodeReference[any]{Value: v, ValueNode: ext.Value}
func extractPaths(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
_, ln, vn := utils.FindKeyNodeFull(v3.PathsLabel, info.RootNode.Content)
if vn != nil {
ir := v3.Paths{}
err := ir.Build(vn, idx)
if err != nil {
return err
}
nr := low.NodeReference[*v3.Paths]{Value: &ir, ValueNode: vn, KeyNode: ln}
doc.Paths = nr
}
return extensionMap, nil
return nil
}

View File

@@ -1,109 +1,109 @@
package openapi
import (
"github.com/pb33f/libopenapi/datamodel"
v3 "github.com/pb33f/libopenapi/datamodel/low/3.0"
"github.com/stretchr/testify/assert"
"io/ioutil"
"testing"
"github.com/pb33f/libopenapi/datamodel"
v3 "github.com/pb33f/libopenapi/datamodel/low/3.0"
"github.com/stretchr/testify/assert"
"io/ioutil"
"testing"
)
var doc *v3.Document
func init() {
data, _ := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
info, _ := datamodel.ExtractSpecInfo(data)
doc, _ = CreateDocument(info)
data, _ := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
info, _ := datamodel.ExtractSpecInfo(data)
doc, _ = CreateDocument(info)
}
func BenchmarkCreateDocument(b *testing.B) {
data, _ := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
info, _ := datamodel.ExtractSpecInfo(data)
for i := 0; i < b.N; i++ {
doc, _ = CreateDocument(info)
}
data, _ := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
info, _ := datamodel.ExtractSpecInfo(data)
for i := 0; i < b.N; i++ {
doc, _ = CreateDocument(info)
}
}
func TestCreateDocument(t *testing.T) {
assert.Equal(t, "3.0.1", doc.Version.Value)
assert.Equal(t, "Burger Shop", doc.Info.Value.Title.Value)
assert.NotEmpty(t, doc.Info.Value.Title.Value)
assert.Equal(t, "3.0.1", doc.Version.Value)
assert.Equal(t, "Burger Shop", doc.Info.Value.Title.Value)
assert.NotEmpty(t, doc.Info.Value.Title.Value)
}
func TestCreateDocument_Info(t *testing.T) {
assert.Equal(t, "https://pb33f.io", doc.Info.Value.TermsOfService.Value)
assert.Equal(t, "pb33f", doc.Info.Value.Contact.Value.Name.Value)
assert.Equal(t, "buckaroo@pb33f.io", doc.Info.Value.Contact.Value.Email.Value)
assert.Equal(t, "https://pb33f.io", doc.Info.Value.Contact.Value.URL.Value)
assert.Equal(t, "pb33f", doc.Info.Value.License.Value.Name.Value)
assert.Equal(t, "https://pb33f.io/made-up", doc.Info.Value.License.Value.URL.Value)
assert.Equal(t, "https://pb33f.io", doc.Info.Value.TermsOfService.Value)
assert.Equal(t, "pb33f", doc.Info.Value.Contact.Value.Name.Value)
assert.Equal(t, "buckaroo@pb33f.io", doc.Info.Value.Contact.Value.Email.Value)
assert.Equal(t, "https://pb33f.io", doc.Info.Value.Contact.Value.URL.Value)
assert.Equal(t, "pb33f", doc.Info.Value.License.Value.Name.Value)
assert.Equal(t, "https://pb33f.io/made-up", doc.Info.Value.License.Value.URL.Value)
}
func TestCreateDocument_Servers(t *testing.T) {
assert.Len(t, doc.Servers, 2)
server1 := doc.Servers[0]
server2 := doc.Servers[1]
assert.Len(t, doc.Servers, 2)
server1 := doc.Servers[0]
server2 := doc.Servers[1]
// server 1
assert.Equal(t, "{scheme}://api.pb33f.io", server1.Value.URL.Value)
assert.NotEmpty(t, server1.Value.Description.Value)
assert.Len(t, server1.Value.Variables.Value, 1)
assert.Len(t, server1.Value.Variables.Value["scheme"].Value.Enum, 2)
assert.Equal(t, server1.Value.Variables.Value["scheme"].Value.Default.Value, "https")
assert.NotEmpty(t, server1.Value.Variables.Value["scheme"].Value.Description.Value)
// server 1
assert.Equal(t, "{scheme}://api.pb33f.io", server1.Value.URL.Value)
assert.NotEmpty(t, server1.Value.Description.Value)
assert.Len(t, server1.Value.Variables.Value, 1)
assert.Len(t, server1.Value.Variables.Value["scheme"].Value.Enum, 2)
assert.Equal(t, server1.Value.Variables.Value["scheme"].Value.Default.Value, "https")
assert.NotEmpty(t, server1.Value.Variables.Value["scheme"].Value.Description.Value)
// server 2
assert.Equal(t, "https://{domain}.{host}.com", server2.Value.URL.Value)
assert.NotEmpty(t, server2.Value.Description.Value)
assert.Len(t, server2.Value.Variables.Value, 2)
assert.Equal(t, server2.Value.Variables.Value["domain"].Value.Default.Value, "api")
assert.NotEmpty(t, server2.Value.Variables.Value["domain"].Value.Description.Value)
assert.NotEmpty(t, server2.Value.Variables.Value["host"].Value.Description.Value)
assert.Equal(t, server2.Value.Variables.Value["host"].Value.Default.Value, "pb33f.io")
assert.Equal(t, "1.2", doc.Info.Value.Version.Value)
// server 2
assert.Equal(t, "https://{domain}.{host}.com", server2.Value.URL.Value)
assert.NotEmpty(t, server2.Value.Description.Value)
assert.Len(t, server2.Value.Variables.Value, 2)
assert.Equal(t, server2.Value.Variables.Value["domain"].Value.Default.Value, "api")
assert.NotEmpty(t, server2.Value.Variables.Value["domain"].Value.Description.Value)
assert.NotEmpty(t, server2.Value.Variables.Value["host"].Value.Description.Value)
assert.Equal(t, server2.Value.Variables.Value["host"].Value.Default.Value, "pb33f.io")
assert.Equal(t, "1.2", doc.Info.Value.Version.Value)
}
func TestCreateDocument_Tags(t *testing.T) {
assert.Len(t, doc.Tags, 2)
assert.Len(t, doc.Tags, 2)
// tag1
assert.Equal(t, "Burgers", doc.Tags[0].Value.Name.Value)
assert.NotEmpty(t, doc.Tags[0].Value.Description.Value)
assert.NotNil(t, doc.Tags[0].Value.ExternalDocs.Value)
assert.Equal(t, "https://pb33f.io", doc.Tags[0].Value.ExternalDocs.Value.URL.Value)
assert.NotEmpty(t, doc.Tags[0].Value.ExternalDocs.Value.URL.Value)
assert.Len(t, doc.Tags[0].Value.Extensions, 7)
// tag1
assert.Equal(t, "Burgers", doc.Tags[0].Value.Name.Value)
assert.NotEmpty(t, doc.Tags[0].Value.Description.Value)
assert.NotNil(t, doc.Tags[0].Value.ExternalDocs.Value)
assert.Equal(t, "https://pb33f.io", doc.Tags[0].Value.ExternalDocs.Value.URL.Value)
assert.NotEmpty(t, doc.Tags[0].Value.ExternalDocs.Value.URL.Value)
assert.Len(t, doc.Tags[0].Value.Extensions, 7)
for key, extension := range doc.Tags[0].Value.Extensions {
switch key.Value {
case "x-internal-ting":
assert.Equal(t, "somethingSpecial", extension.Value)
case "x-internal-tong":
assert.Equal(t, int64(1), extension.Value)
case "x-internal-tang":
assert.Equal(t, 1.2, extension.Value)
case "x-internal-tung":
assert.Equal(t, true, extension.Value)
case "x-internal-arr":
assert.Len(t, extension.Value, 2)
assert.Equal(t, "one", extension.Value.([]interface{})[0].(string))
case "x-internal-arrmap":
assert.Len(t, extension.Value, 2)
assert.Equal(t, "now", extension.Value.([]interface{})[0].(map[string]interface{})["what"])
case "x-something-else":
// crazy times in the upside down. this API should be avoided for the higher up use cases.
// this is why we will need a higher level API to this model, this looks cool and all, but dude.
assert.Equal(t, "now?", extension.Value.(map[string]interface{})["ok"].([]interface{})[0].(map[string]interface{})["what"])
}
for key, extension := range doc.Tags[0].Value.Extensions {
switch key.Value {
case "x-internal-ting":
assert.Equal(t, "somethingSpecial", extension.Value)
case "x-internal-tong":
assert.Equal(t, int64(1), extension.Value)
case "x-internal-tang":
assert.Equal(t, 1.2, extension.Value)
case "x-internal-tung":
assert.Equal(t, true, extension.Value)
case "x-internal-arr":
assert.Len(t, extension.Value, 2)
assert.Equal(t, "one", extension.Value.([]interface{})[0].(string))
case "x-internal-arrmap":
assert.Len(t, extension.Value, 2)
assert.Equal(t, "now", extension.Value.([]interface{})[0].(map[string]interface{})["what"])
case "x-something-else":
// crazy times in the upside down. this API should be avoided for the higher up use cases.
// this is why we will need a higher level API to this model, this looks cool and all, but dude.
assert.Equal(t, "now?", extension.Value.(map[string]interface{})["ok"].([]interface{})[0].(map[string]interface{})["what"])
}
}
}
/// tag2
assert.Equal(t, "Dressing", doc.Tags[1].Value.Name.Value)
assert.NotEmpty(t, doc.Tags[1].Value.Description.Value)
assert.NotNil(t, doc.Tags[1].Value.ExternalDocs.Value)
assert.Equal(t, "https://pb33f.io", doc.Tags[1].Value.ExternalDocs.Value.URL.Value)
assert.NotEmpty(t, doc.Tags[1].Value.ExternalDocs.Value.URL.Value)
assert.Len(t, doc.Tags[1].Value.Extensions, 0)
/// tag2
assert.Equal(t, "Dressing", doc.Tags[1].Value.Name.Value)
assert.NotEmpty(t, doc.Tags[1].Value.Description.Value)
assert.NotNil(t, doc.Tags[1].Value.ExternalDocs.Value)
assert.Equal(t, "https://pb33f.io", doc.Tags[1].Value.ExternalDocs.Value.URL.Value)
assert.NotEmpty(t, doc.Tags[1].Value.ExternalDocs.Value.URL.Value)
assert.Len(t, doc.Tags[1].Value.Extensions, 0)
}

View File

@@ -54,7 +54,11 @@ servers:
default: "pb33f.io"
description: the default host for this API is 'pb33f.com'
paths:
x-milky-milk: milky
/refingtons:
$ref: '../test_specs/petstorev3.json#/paths~1pet~1findByStatus'
/burgers:
x-burger-meta: meaty
post:
operationId: createBurger
tags:
@@ -385,3 +389,4 @@ components:
type: string
description: what size man? S/M/L
example: M

View File

@@ -448,7 +448,7 @@ func IsHttpVerb(verb string) bool {
func ConvertComponentIdIntoFriendlyPathSearch(id string) (string, string) {
segs := strings.Split(id, "/")
name := segs[len(segs)-1]
name := strings.ReplaceAll(segs[len(segs)-1], "~1", "/")
replaced := strings.ReplaceAll(fmt.Sprintf("%s['%s']",
strings.Join(segs[:len(segs)-1], "."), name), "#", "$")