mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-07 04:20:14 +00:00
resolver tests all operational
time to start some cleanup. Signed-off-by: quobix <dave@quobix.com>
This commit is contained in:
@@ -90,9 +90,9 @@ func LocateRefNode(root *yaml.Node, idx *index.SpecIndex) (*yaml.Node, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perform a search for the reference in the index
|
// perform a search for the reference in the index
|
||||||
foundRefs := idx.SearchIndexForReference(rv)
|
foundRef := idx.SearchIndexForReference(rv)
|
||||||
if len(foundRefs) > 0 {
|
if foundRef != nil {
|
||||||
return utils.NodeAlias(foundRefs[0].Node), nil
|
return utils.NodeAlias(foundRef.Node), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// let's try something else to find our references.
|
// let's try something else to find our references.
|
||||||
|
|||||||
@@ -467,14 +467,14 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(seenPath) > 0 {
|
//if len(seenPath) > 0 {
|
||||||
seenPath = seenPath[:len(seenPath)-1]
|
// seenPath = seenPath[:len(seenPath)-1]
|
||||||
}
|
//}
|
||||||
|
|
||||||
}
|
}
|
||||||
if len(seenPath) > 0 {
|
//if len(seenPath) > 0 {
|
||||||
seenPath = seenPath[:len(seenPath)-1]
|
// seenPath = seenPath[:len(seenPath)-1]
|
||||||
}
|
//}
|
||||||
|
|
||||||
index.refCount = len(index.allRefs)
|
index.refCount = len(index.allRefs)
|
||||||
|
|
||||||
@@ -487,7 +487,7 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc
|
|||||||
var found []*Reference
|
var found []*Reference
|
||||||
|
|
||||||
// run this async because when things get recursive, it can take a while
|
// run this async because when things get recursive, it can take a while
|
||||||
//c := make(chan bool)
|
c := make(chan bool)
|
||||||
|
|
||||||
locate := func(ref *Reference, refIndex int, sequence []*ReferenceMapped) {
|
locate := func(ref *Reference, refIndex int, sequence []*ReferenceMapped) {
|
||||||
located := index.FindComponent(ref.FullDefinition, ref.Node)
|
located := index.FindComponent(ref.FullDefinition, ref.Node)
|
||||||
@@ -532,7 +532,7 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc
|
|||||||
index.refErrors = append(index.refErrors, indexError)
|
index.refErrors = append(index.refErrors, indexError)
|
||||||
index.errorLock.Unlock()
|
index.errorLock.Unlock()
|
||||||
}
|
}
|
||||||
//c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
var refsToCheck []*Reference
|
var refsToCheck []*Reference
|
||||||
@@ -556,17 +556,17 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc
|
|||||||
|
|
||||||
for r := range refsToCheck {
|
for r := range refsToCheck {
|
||||||
// expand our index of all mapped refs
|
// expand our index of all mapped refs
|
||||||
//go locate(refsToCheck[r], r, mappedRefsInSequence)
|
go locate(refsToCheck[r], r, mappedRefsInSequence)
|
||||||
locate(refsToCheck[r], r, mappedRefsInSequence) // used for sync testing.
|
//locate(refsToCheck[r], r, mappedRefsInSequence) // used for sync testing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//completedRefs := 0
|
completedRefs := 0
|
||||||
//for completedRefs < len(refsToCheck) {
|
for completedRefs < len(refsToCheck) {
|
||||||
// select {
|
select {
|
||||||
// case <-c:
|
case <-c:
|
||||||
// completedRefs++
|
completedRefs++
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
for m := range mappedRefsInSequence {
|
for m := range mappedRefsInSequence {
|
||||||
if mappedRefsInSequence[m] != nil {
|
if mappedRefsInSequence[m] != nil {
|
||||||
index.allMappedRefsSequenced = append(index.allMappedRefsSequenced, mappedRefsInSequence[m])
|
index.allMappedRefsSequenced = append(index.allMappedRefsSequenced, mappedRefsInSequence[m])
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResolvingError represents an issue the resolver had trying to stitch the tree together.
|
// ResolvingError represents an issue the resolver had trying to stitch the tree together.
|
||||||
@@ -215,7 +216,6 @@ func visitIndex(res *Resolver, idx *SpecIndex) {
|
|||||||
mapped := idx.GetMappedReferencesSequenced()
|
mapped := idx.GetMappedReferencesSequenced()
|
||||||
mappedIndex := idx.GetMappedReferences()
|
mappedIndex := idx.GetMappedReferences()
|
||||||
res.indexesVisited++
|
res.indexesVisited++
|
||||||
|
|
||||||
for _, ref := range mapped {
|
for _, ref := range mapped {
|
||||||
seenReferences := make(map[string]bool)
|
seenReferences := make(map[string]bool)
|
||||||
var journey []*Reference
|
var journey []*Reference
|
||||||
@@ -244,9 +244,6 @@ func visitIndex(res *Resolver, idx *SpecIndex) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//for _, c := range idx.GetChildren() {
|
|
||||||
// visitIndex(res, c)
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VisitReference will visit a reference as part of a journey and will return resolved nodes.
|
// VisitReference will visit a reference as part of a journey and will return resolved nodes.
|
||||||
@@ -269,9 +266,9 @@ func (resolver *Resolver) VisitReference(ref *Reference, seen map[string]bool, j
|
|||||||
if j.Definition == r.Definition {
|
if j.Definition == r.Definition {
|
||||||
|
|
||||||
var foundDup *Reference
|
var foundDup *Reference
|
||||||
foundRefs := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
foundRef := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
||||||
if len(foundRefs) > 0 {
|
if foundRef != nil {
|
||||||
foundDup = foundRefs[0]
|
foundDup = foundRef
|
||||||
}
|
}
|
||||||
|
|
||||||
var circRef *CircularReferenceResult
|
var circRef *CircularReferenceResult
|
||||||
@@ -295,10 +292,8 @@ func (resolver *Resolver) VisitReference(ref *Reference, seen map[string]bool, j
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resolver.IgnoreArray && isArray {
|
if resolver.IgnoreArray && isArray {
|
||||||
fmt.Printf("Ignored: %s\n", circRef.GenerateJourneyPath())
|
|
||||||
resolver.ignoredArrayReferences = append(resolver.ignoredArrayReferences, circRef)
|
resolver.ignoredArrayReferences = append(resolver.ignoredArrayReferences, circRef)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Not Ignored: %s\n", circRef.GenerateJourneyPath())
|
|
||||||
resolver.circularReferences = append(resolver.circularReferences, circRef)
|
resolver.circularReferences = append(resolver.circularReferences, circRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,9 +306,9 @@ func (resolver *Resolver) VisitReference(ref *Reference, seen map[string]bool, j
|
|||||||
|
|
||||||
if !skip {
|
if !skip {
|
||||||
var original *Reference
|
var original *Reference
|
||||||
foundRefs := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
foundRef := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
||||||
if len(foundRefs) > 0 {
|
if foundRef != nil {
|
||||||
original = foundRefs[0]
|
original = foundRef
|
||||||
}
|
}
|
||||||
resolved := resolver.VisitReference(original, seen, journey, resolve)
|
resolved := resolver.VisitReference(original, seen, journey, resolve)
|
||||||
if resolve && !original.Circular {
|
if resolve && !original.Circular {
|
||||||
@@ -408,10 +403,23 @@ func (resolver *Resolver) extractRelatives(ref *Reference, node, parent *yaml.No
|
|||||||
}
|
}
|
||||||
|
|
||||||
value := node.Content[i+1].Value
|
value := node.Content[i+1].Value
|
||||||
var locatedRef []*Reference
|
var locatedRef *Reference
|
||||||
|
|
||||||
|
var fullDef string
|
||||||
|
exp := strings.Split(ref.FullDefinition, "#/")
|
||||||
|
if len(exp) == 2 {
|
||||||
|
if exp[0] != "" {
|
||||||
|
fullDef = fmt.Sprintf("%s%s", exp[0], value)
|
||||||
|
} else {
|
||||||
|
fullDef = value
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fullDef = value
|
||||||
|
}
|
||||||
|
|
||||||
searchRef := &Reference{
|
searchRef := &Reference{
|
||||||
Definition: value,
|
Definition: value,
|
||||||
FullDefinition: ref.FullDefinition,
|
FullDefinition: fullDef,
|
||||||
RemoteLocation: ref.RemoteLocation,
|
RemoteLocation: ref.RemoteLocation,
|
||||||
IsRemote: true,
|
IsRemote: true,
|
||||||
}
|
}
|
||||||
@@ -451,10 +459,8 @@ func (resolver *Resolver) extractRelatives(ref *Reference, node, parent *yaml.No
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
locatedRef[0].ParentNodeSchemaType = schemaType
|
locatedRef.ParentNodeSchemaType = schemaType
|
||||||
|
found = append(found, locatedRef)
|
||||||
found = append(found, locatedRef[0])
|
|
||||||
|
|
||||||
foundRelatives[value] = true
|
foundRelatives[value] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -24,27 +24,15 @@ func Benchmark_ResolveDocumentStripe(b *testing.B) {
|
|||||||
var rootNode yaml.Node
|
var rootNode yaml.Node
|
||||||
_ = yaml.Unmarshal(resolveFile, &rootNode)
|
_ = yaml.Unmarshal(resolveFile, &rootNode)
|
||||||
|
|
||||||
fileFS, err := NewLocalFS(baseDir, os.DirFS(filepath.Dir(baseDir)))
|
|
||||||
|
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cf := CreateOpenAPIIndexConfig()
|
cf := CreateOpenAPIIndexConfig()
|
||||||
cf.AvoidBuildIndex = true
|
|
||||||
|
|
||||||
rolo := NewRolodex(cf)
|
rolo := NewRolodex(cf)
|
||||||
rolo.SetRootNode(&rootNode)
|
rolo.SetRootNode(&rootNode)
|
||||||
cf.Rolodex = rolo
|
|
||||||
|
|
||||||
// TODO: pick up here.
|
|
||||||
|
|
||||||
rolo.AddLocalFS(baseDir, fileFS)
|
|
||||||
|
|
||||||
indexedErr := rolo.IndexTheRolodex()
|
indexedErr := rolo.IndexTheRolodex()
|
||||||
assert.Error(b, indexedErr)
|
assert.Len(b, utils.UnwrapErrors(indexedErr), 3)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -407,20 +395,16 @@ func TestResolver_ResolveComponents_Stripe(t *testing.T) {
|
|||||||
|
|
||||||
resolveFile, _ := os.ReadFile(baseDir)
|
resolveFile, _ := os.ReadFile(baseDir)
|
||||||
|
|
||||||
|
var stripeRoot yaml.Node
|
||||||
|
_ = yaml.Unmarshal(resolveFile, &stripeRoot)
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfoWithDocumentCheck(resolveFile, true)
|
info, _ := datamodel.ExtractSpecInfoWithDocumentCheck(resolveFile, true)
|
||||||
|
|
||||||
fileFS, err := NewLocalFS(baseDir, os.DirFS(filepath.Dir(baseDir)))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cf := CreateOpenAPIIndexConfig()
|
cf := CreateOpenAPIIndexConfig()
|
||||||
//cf.AvoidBuildIndex = true
|
|
||||||
cf.SpecInfo = info
|
cf.SpecInfo = info
|
||||||
rolo := NewRolodex(cf)
|
|
||||||
cf.Rolodex = rolo
|
|
||||||
|
|
||||||
rolo.AddLocalFS(baseDir, fileFS)
|
rolo := NewRolodex(cf)
|
||||||
|
rolo.SetRootNode(&stripeRoot)
|
||||||
|
|
||||||
indexedErr := rolo.IndexTheRolodex()
|
indexedErr := rolo.IndexTheRolodex()
|
||||||
|
|
||||||
@@ -545,20 +529,67 @@ func TestResolver_ResolveComponents_MixedRef(t *testing.T) {
|
|||||||
var rootNode yaml.Node
|
var rootNode yaml.Node
|
||||||
_ = yaml.Unmarshal(mixedref, &rootNode)
|
_ = yaml.Unmarshal(mixedref, &rootNode)
|
||||||
|
|
||||||
b := CreateOpenAPIIndexConfig()
|
// create a test server.
|
||||||
idx := NewSpecIndexWithConfig(&rootNode, b)
|
server := test_buildMixedRefServer()
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
resolver := NewResolver(idx)
|
// create a new config that allows local and remote to be mixed up.
|
||||||
assert.NotNil(t, resolver)
|
cf := CreateOpenAPIIndexConfig()
|
||||||
|
cf.AvoidBuildIndex = true
|
||||||
|
cf.AllowRemoteLookup = true
|
||||||
|
cf.AvoidCircularReferenceCheck = true
|
||||||
|
cf.BasePath = "../test_specs"
|
||||||
|
|
||||||
circ := resolver.Resolve()
|
// setting this baseURL will override the base
|
||||||
assert.Len(t, circ, 0)
|
cf.BaseURL, _ = url.Parse(server.URL)
|
||||||
assert.Equal(t, 5, resolver.GetIndexesVisited())
|
|
||||||
|
// create a new rolodex
|
||||||
|
rolo := NewRolodex(cf)
|
||||||
|
|
||||||
|
// set the rolodex root node to the root node of the spec.
|
||||||
|
rolo.SetRootNode(&rootNode)
|
||||||
|
|
||||||
|
// create a new remote fs and set the config for indexing.
|
||||||
|
remoteFS, _ := NewRemoteFSWithRootURL(server.URL)
|
||||||
|
remoteFS.SetIndexConfig(cf)
|
||||||
|
|
||||||
|
// set our remote handler func
|
||||||
|
|
||||||
|
c := http.Client{}
|
||||||
|
|
||||||
|
remoteFS.RemoteHandlerFunc = c.Get
|
||||||
|
|
||||||
|
// configure the local filesystem.
|
||||||
|
fsCfg := LocalFSConfig{
|
||||||
|
BaseDirectory: cf.BasePath,
|
||||||
|
FileFilters: []string{"burgershop.openapi.yaml"},
|
||||||
|
DirFS: os.DirFS(cf.BasePath),
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new local filesystem.
|
||||||
|
fileFS, err := NewLocalFSWithConfig(&fsCfg)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// add file systems to the rolodex
|
||||||
|
rolo.AddLocalFS(cf.BasePath, fileFS)
|
||||||
|
rolo.AddRemoteFS(server.URL, remoteFS)
|
||||||
|
|
||||||
|
// index the rolodex.
|
||||||
|
indexedErr := rolo.IndexTheRolodex()
|
||||||
|
|
||||||
|
assert.NoError(t, indexedErr)
|
||||||
|
|
||||||
|
rolo.Resolve()
|
||||||
|
index := rolo.GetRootIndex
|
||||||
|
resolver := index().GetResolver()
|
||||||
|
|
||||||
|
assert.Len(t, resolver.GetCircularErrors(), 0)
|
||||||
|
assert.Equal(t, 3, resolver.GetIndexesVisited())
|
||||||
|
|
||||||
// in v0.8.2 a new check was added when indexing, to prevent re-indexing the same file multiple times.
|
// in v0.8.2 a new check was added when indexing, to prevent re-indexing the same file multiple times.
|
||||||
assert.Equal(t, 191, resolver.GetRelativesSeen())
|
assert.Equal(t, 6, resolver.GetRelativesSeen())
|
||||||
assert.Equal(t, 35, resolver.GetJourneysTaken())
|
assert.Equal(t, 5, resolver.GetJourneysTaken())
|
||||||
assert.Equal(t, 62, resolver.GetReferenceVisited())
|
assert.Equal(t, 7, resolver.GetReferenceVisited())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResolver_ResolveComponents_k8s(t *testing.T) {
|
func TestResolver_ResolveComponents_k8s(t *testing.T) {
|
||||||
|
|||||||
@@ -356,18 +356,18 @@ func (r *Rolodex) IndexTheRolodex() error {
|
|||||||
|
|
||||||
// now that we have indexed all the files, we can build the index.
|
// now that we have indexed all the files, we can build the index.
|
||||||
r.indexes = indexBuildQueue
|
r.indexes = indexBuildQueue
|
||||||
if !r.indexConfig.AvoidBuildIndex {
|
//if !r.indexConfig.AvoidBuildIndex {
|
||||||
for _, idx := range indexBuildQueue {
|
for _, idx := range indexBuildQueue {
|
||||||
idx.BuildIndex()
|
idx.BuildIndex()
|
||||||
if r.indexConfig.AvoidCircularReferenceCheck {
|
if r.indexConfig.AvoidCircularReferenceCheck {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
errs := idx.resolver.CheckForCircularReferences()
|
errs := idx.resolver.CheckForCircularReferences()
|
||||||
for e := range errs {
|
for e := range errs {
|
||||||
caughtErrors = append(caughtErrors, errs[e])
|
caughtErrors = append(caughtErrors, errs[e])
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
// indexed and built every supporting file, we can build the root index (our entry point)
|
// indexed and built every supporting file, we can build the root index (our entry point)
|
||||||
|
|
||||||
@@ -453,7 +453,7 @@ func (r *Rolodex) Open(location string) (RolodexFile, error) {
|
|||||||
var remoteFile *RemoteFile
|
var remoteFile *RemoteFile
|
||||||
|
|
||||||
if r == nil || r.localFS == nil && r.remoteFS == nil {
|
if r == nil || r.localFS == nil && r.remoteFS == nil {
|
||||||
panic("WHAT NO....")
|
return nil, fmt.Errorf("rolodex has no file systems configured, cannot open '%s'", location)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileLookup := location
|
fileLookup := location
|
||||||
|
|||||||
@@ -4,192 +4,192 @@
|
|||||||
package index
|
package index
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var test_httpClient = &http.Client{Timeout: time.Duration(60) * time.Second}
|
var test_httpClient = &http.Client{Timeout: time.Duration(60) * time.Second}
|
||||||
|
|
||||||
func test_buildServer() *httptest.Server {
|
func test_buildServer() *httptest.Server {
|
||||||
return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
if req.URL.String() == "/file1.yaml" {
|
if req.URL.String() == "/file1.yaml" {
|
||||||
rw.Header().Set("Last-Modified", "Wed, 21 Oct 2015 07:28:00 GMT")
|
rw.Header().Set("Last-Modified", "Wed, 21 Oct 2015 07:28:00 GMT")
|
||||||
_, _ = rw.Write([]byte(`"$ref": "./deeper/file2.yaml#/components/schemas/Pet"`))
|
_, _ = rw.Write([]byte(`"$ref": "./deeper/file2.yaml#/components/schemas/Pet"`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.URL.String() == "/deeper/file2.yaml" {
|
if req.URL.String() == "/deeper/file2.yaml" {
|
||||||
rw.Header().Set("Last-Modified", "Wed, 21 Oct 2015 08:28:00 GMT")
|
rw.Header().Set("Last-Modified", "Wed, 21 Oct 2015 08:28:00 GMT")
|
||||||
_, _ = rw.Write([]byte(`"$ref": "/deeper/even_deeper/file3.yaml#/components/schemas/Pet"`))
|
_, _ = rw.Write([]byte(`"$ref": "/deeper/even_deeper/file3.yaml#/components/schemas/Pet"`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.URL.String() == "/deeper/even_deeper/file3.yaml" {
|
if req.URL.String() == "/deeper/even_deeper/file3.yaml" {
|
||||||
rw.Header().Set("Last-Modified", "Wed, 21 Oct 2015 10:28:00 GMT")
|
rw.Header().Set("Last-Modified", "Wed, 21 Oct 2015 10:28:00 GMT")
|
||||||
_, _ = rw.Write([]byte(`"$ref": "../file2.yaml#/components/schemas/Pet"`))
|
_, _ = rw.Write([]byte(`"$ref": "../file2.yaml#/components/schemas/Pet"`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rw.Header().Set("Last-Modified", "Wed, 21 Oct 2015 12:28:00 GMT")
|
rw.Header().Set("Last-Modified", "Wed, 21 Oct 2015 12:28:00 GMT")
|
||||||
|
|
||||||
if req.URL.String() == "/deeper/list.yaml" {
|
if req.URL.String() == "/deeper/list.yaml" {
|
||||||
_, _ = rw.Write([]byte(`"$ref": "../file2.yaml"`))
|
_, _ = rw.Write([]byte(`"$ref": "../file2.yaml"`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.URL.String() == "/bag/list.yaml" {
|
if req.URL.String() == "/bag/list.yaml" {
|
||||||
_, _ = rw.Write([]byte(`"$ref": "pocket/list.yaml"\n\n"$ref": "zip/things.yaml"`))
|
_, _ = rw.Write([]byte(`"$ref": "pocket/list.yaml"\n\n"$ref": "zip/things.yaml"`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.URL.String() == "/bag/pocket/list.yaml" {
|
if req.URL.String() == "/bag/pocket/list.yaml" {
|
||||||
_, _ = rw.Write([]byte(`"$ref": "../list.yaml"\n\n"$ref": "../../file2.yaml"`))
|
_, _ = rw.Write([]byte(`"$ref": "../list.yaml"\n\n"$ref": "../../file2.yaml"`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.URL.String() == "/bag/pocket/things.yaml" {
|
if req.URL.String() == "/bag/pocket/things.yaml" {
|
||||||
_, _ = rw.Write([]byte(`"$ref": "list.yaml"`))
|
_, _ = rw.Write([]byte(`"$ref": "list.yaml"`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.URL.String() == "/bag/zip/things.yaml" {
|
if req.URL.String() == "/bag/zip/things.yaml" {
|
||||||
_, _ = rw.Write([]byte(`"$ref": "list.yaml"`))
|
_, _ = rw.Write([]byte(`"$ref": "list.yaml"`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.URL.String() == "/bag/zip/list.yaml" {
|
if req.URL.String() == "/bag/zip/list.yaml" {
|
||||||
_, _ = rw.Write([]byte(`"$ref": "../list.yaml"\n\n"$ref": "../../file1.yaml"\n\n"$ref": "more.yaml""`))
|
_, _ = rw.Write([]byte(`"$ref": "../list.yaml"\n\n"$ref": "../../file1.yaml"\n\n"$ref": "more.yaml""`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.URL.String() == "/bag/zip/more.yaml" {
|
if req.URL.String() == "/bag/zip/more.yaml" {
|
||||||
_, _ = rw.Write([]byte(`"$ref": "../../deeper/list.yaml"\n\n"$ref": "../../bad.yaml"`))
|
_, _ = rw.Write([]byte(`"$ref": "../../deeper/list.yaml"\n\n"$ref": "../../bad.yaml"`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.URL.String() == "/bad.yaml" {
|
if req.URL.String() == "/bad.yaml" {
|
||||||
rw.WriteHeader(http.StatusInternalServerError)
|
rw.WriteHeader(http.StatusInternalServerError)
|
||||||
_, _ = rw.Write([]byte(`"error, cannot do the thing"`))
|
_, _ = rw.Write([]byte(`"error, cannot do the thing"`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = rw.Write([]byte(`OK`))
|
_, _ = rw.Write([]byte(`OK`))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewRemoteFS_BasicCheck(t *testing.T) {
|
func TestNewRemoteFS_BasicCheck(t *testing.T) {
|
||||||
|
|
||||||
server := test_buildServer()
|
server := test_buildServer()
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
//remoteFS := NewRemoteFS("https://raw.githubusercontent.com/digitalocean/openapi/main/specification/")
|
//remoteFS := NewRemoteFS("https://raw.githubusercontent.com/digitalocean/openapi/main/specification/")
|
||||||
remoteFS, _ := NewRemoteFSWithRootURL(server.URL)
|
remoteFS, _ := NewRemoteFSWithRootURL(server.URL)
|
||||||
remoteFS.RemoteHandlerFunc = test_httpClient.Get
|
remoteFS.RemoteHandlerFunc = test_httpClient.Get
|
||||||
|
|
||||||
file, err := remoteFS.Open("/file1.yaml")
|
file, err := remoteFS.Open("/file1.yaml")
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
bytes, rErr := io.ReadAll(file)
|
bytes, rErr := io.ReadAll(file)
|
||||||
assert.NoError(t, rErr)
|
assert.NoError(t, rErr)
|
||||||
|
|
||||||
assert.Equal(t, "\"$ref\": \"\"./deeper/file2.yaml#/components/schemas/Pet\"", string(bytes))
|
assert.Equal(t, "\"$ref\": \"\"./deeper/file2.yaml#/components/schemas/Pet\"", string(bytes))
|
||||||
|
|
||||||
stat, _ := file.Stat()
|
stat, _ := file.Stat()
|
||||||
|
|
||||||
assert.Equal(t, "file1.yaml", stat.Name())
|
assert.Equal(t, "file1.yaml", stat.Name())
|
||||||
assert.Equal(t, int64(54), stat.Size())
|
assert.Equal(t, int64(54), stat.Size())
|
||||||
|
|
||||||
lastMod := stat.ModTime()
|
lastMod := stat.ModTime()
|
||||||
assert.Equal(t, "2015-10-21 07:28:00 +0000 GMT", lastMod.String())
|
assert.Equal(t, "2015-10-21 07:28:00 +0000 GMT", lastMod.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewRemoteFS_BasicCheck_Relative(t *testing.T) {
|
func TestNewRemoteFS_BasicCheck_Relative(t *testing.T) {
|
||||||
|
|
||||||
server := test_buildServer()
|
server := test_buildServer()
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
remoteFS, _ := NewRemoteFSWithRootURL(server.URL)
|
remoteFS, _ := NewRemoteFSWithRootURL(server.URL)
|
||||||
remoteFS.RemoteHandlerFunc = test_httpClient.Get
|
remoteFS.RemoteHandlerFunc = test_httpClient.Get
|
||||||
|
|
||||||
file, err := remoteFS.Open("/deeper/file2.yaml")
|
file, err := remoteFS.Open("/deeper/file2.yaml")
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
bytes, rErr := io.ReadAll(file)
|
bytes, rErr := io.ReadAll(file)
|
||||||
assert.NoError(t, rErr)
|
assert.NoError(t, rErr)
|
||||||
|
|
||||||
assert.Equal(t, "\"$ref\": \"./deeper/even_deeper/file3.yaml#/components/schemas/Pet\"", string(bytes))
|
assert.Equal(t, "\"$ref\": \"./deeper/even_deeper/file3.yaml#/components/schemas/Pet\"", string(bytes))
|
||||||
|
|
||||||
stat, _ := file.Stat()
|
stat, _ := file.Stat()
|
||||||
|
|
||||||
assert.Equal(t, "/deeper/file2.yaml", stat.Name())
|
assert.Equal(t, "/deeper/file2.yaml", stat.Name())
|
||||||
assert.Equal(t, int64(65), stat.Size())
|
assert.Equal(t, int64(65), stat.Size())
|
||||||
|
|
||||||
lastMod := stat.ModTime()
|
lastMod := stat.ModTime()
|
||||||
assert.Equal(t, "2015-10-21 08:28:00 +0000 GMT", lastMod.String())
|
assert.Equal(t, "2015-10-21 08:28:00 +0000 GMT", lastMod.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewRemoteFS_BasicCheck_Relative_Deeper(t *testing.T) {
|
func TestNewRemoteFS_BasicCheck_Relative_Deeper(t *testing.T) {
|
||||||
|
|
||||||
server := test_buildServer()
|
server := test_buildServer()
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
remoteFS, _ := NewRemoteFSWithRootURL(server.URL)
|
remoteFS, _ := NewRemoteFSWithRootURL(server.URL)
|
||||||
remoteFS.RemoteHandlerFunc = test_httpClient.Get
|
remoteFS.RemoteHandlerFunc = test_httpClient.Get
|
||||||
|
|
||||||
file, err := remoteFS.Open("/deeper/even_deeper/file3.yaml")
|
file, err := remoteFS.Open("/deeper/even_deeper/file3.yaml")
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
bytes, rErr := io.ReadAll(file)
|
bytes, rErr := io.ReadAll(file)
|
||||||
assert.NoError(t, rErr)
|
assert.NoError(t, rErr)
|
||||||
|
|
||||||
assert.Equal(t, "\"$ref\": \"../file2.yaml#/components/schemas/Pet\"", string(bytes))
|
assert.Equal(t, "\"$ref\": \"../file2.yaml#/components/schemas/Pet\"", string(bytes))
|
||||||
|
|
||||||
stat, _ := file.Stat()
|
stat, _ := file.Stat()
|
||||||
|
|
||||||
assert.Equal(t, "/deeper/even_deeper/file3.yaml", stat.Name())
|
assert.Equal(t, "/deeper/even_deeper/file3.yaml", stat.Name())
|
||||||
assert.Equal(t, int64(47), stat.Size())
|
assert.Equal(t, int64(47), stat.Size())
|
||||||
|
|
||||||
lastMod := stat.ModTime()
|
lastMod := stat.ModTime()
|
||||||
assert.Equal(t, "2015-10-21 10:28:00 +0000 GMT", lastMod.String())
|
assert.Equal(t, "2015-10-21 10:28:00 +0000 GMT", lastMod.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewRemoteFS_BasicCheck_SeekRelatives(t *testing.T) {
|
func TestNewRemoteFS_BasicCheck_SeekRelatives(t *testing.T) {
|
||||||
|
|
||||||
server := test_buildServer()
|
server := test_buildServer()
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
remoteFS, _ := NewRemoteFSWithRootURL(server.URL)
|
remoteFS, _ := NewRemoteFSWithRootURL(server.URL)
|
||||||
remoteFS.RemoteHandlerFunc = test_httpClient.Get
|
remoteFS.RemoteHandlerFunc = test_httpClient.Get
|
||||||
|
|
||||||
file, err := remoteFS.Open("/bag/list.yaml")
|
file, err := remoteFS.Open("/bag/list.yaml")
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
bytes, rErr := io.ReadAll(file)
|
bytes, rErr := io.ReadAll(file)
|
||||||
assert.NoError(t, rErr)
|
assert.NoError(t, rErr)
|
||||||
|
|
||||||
assert.Equal(t, "\"$ref\": \"pocket/list.yaml\"\\n\\n\"$ref\": \"zip/things.yaml\"", string(bytes))
|
assert.Equal(t, "\"$ref\": \"pocket/list.yaml\"\\n\\n\"$ref\": \"zip/things.yaml\"", string(bytes))
|
||||||
|
|
||||||
stat, _ := file.Stat()
|
stat, _ := file.Stat()
|
||||||
|
|
||||||
assert.Equal(t, "/bag/list.yaml", stat.Name())
|
assert.Equal(t, "/bag/list.yaml", stat.Name())
|
||||||
assert.Equal(t, int64(55), stat.Size())
|
assert.Equal(t, int64(55), stat.Size())
|
||||||
|
|
||||||
lastMod := stat.ModTime()
|
lastMod := stat.ModTime()
|
||||||
assert.Equal(t, "2015-10-21 12:28:00 +0000 GMT", lastMod.String())
|
assert.Equal(t, "2015-10-21 12:28:00 +0000 GMT", lastMod.String())
|
||||||
|
|
||||||
files := remoteFS.GetFiles()
|
files := remoteFS.GetFiles()
|
||||||
assert.Len(t, remoteFS.remoteErrors, 1)
|
assert.Len(t, remoteFS.remoteErrors, 1)
|
||||||
assert.Len(t, files, 10)
|
assert.Len(t, files, 10)
|
||||||
|
|
||||||
// check correct files are in the cache
|
// check correct files are in the cache
|
||||||
assert.Equal(t, "/bag/list.yaml", files["/bag/list.yaml"].GetFullPath())
|
assert.Equal(t, "/bag/list.yaml", files["/bag/list.yaml"].GetFullPath())
|
||||||
assert.Equal(t, "list.yaml", files["/bag/list.yaml"].Name())
|
assert.Equal(t, "list.yaml", files["/bag/list.yaml"].Name())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) []*Reference {
|
func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) *Reference {
|
||||||
|
|
||||||
ref := fullRef.FullDefinition
|
ref := fullRef.FullDefinition
|
||||||
|
|
||||||
@@ -34,28 +34,24 @@ func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) [
|
|||||||
}
|
}
|
||||||
|
|
||||||
if r, ok := index.allMappedRefs[ref]; ok {
|
if r, ok := index.allMappedRefs[ref]; ok {
|
||||||
return []*Reference{r}
|
return r
|
||||||
}
|
|
||||||
|
|
||||||
if r, ok := index.allRefs[ref]; ok {
|
|
||||||
return []*Reference{r}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check the rolodex for the reference.
|
||||||
if roloLookup != "" {
|
if roloLookup != "" {
|
||||||
rFile, err := index.rolodex.Open(roloLookup)
|
rFile, err := index.rolodex.Open(roloLookup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extract the index from the rolodex file.
|
||||||
idx := rFile.GetIndex()
|
idx := rFile.GetIndex()
|
||||||
|
index.resolver.indexesVisited++
|
||||||
if idx != nil {
|
if idx != nil {
|
||||||
|
|
||||||
// check mapped refs.
|
// check mapped refs.
|
||||||
if r, ok := idx.allMappedRefs[ref]; ok {
|
if r, ok := idx.allMappedRefs[ref]; ok {
|
||||||
return []*Reference{r}
|
return r
|
||||||
}
|
|
||||||
|
|
||||||
if r, ok := index.allRefs[ref]; ok {
|
|
||||||
return []*Reference{r}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a collection of all the inline schemas and search them
|
// build a collection of all the inline schemas and search them
|
||||||
@@ -66,7 +62,7 @@ func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) [
|
|||||||
d = append(d, idx.allInlineSchemaObjectDefinitions...)
|
d = append(d, idx.allInlineSchemaObjectDefinitions...)
|
||||||
for _, s := range d {
|
for _, s := range d {
|
||||||
if s.Definition == ref {
|
if s.Definition == ref {
|
||||||
return []*Reference{s}
|
return s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,10 +75,6 @@ func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) [
|
|||||||
// SearchIndexForReference searches the index for a reference, first looking through the mapped references
|
// SearchIndexForReference searches the index for a reference, first looking through the mapped references
|
||||||
// and then externalSpecIndex for a match. If no match is found, it will recursively search the child indexes
|
// and then externalSpecIndex for a match. If no match is found, it will recursively search the child indexes
|
||||||
// extracted when parsing the OpenAPI Spec.
|
// extracted when parsing the OpenAPI Spec.
|
||||||
func (index *SpecIndex) SearchIndexForReference(ref string) []*Reference {
|
func (index *SpecIndex) SearchIndexForReference(ref string) *Reference {
|
||||||
return index.SearchIndexForReferenceByReference(&Reference{FullDefinition: ref})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (index *SpecIndex) SearchIndexForReferenceWithParent(ref string, reference *Reference) []*Reference {
|
|
||||||
return index.SearchIndexForReferenceByReference(&Reference{FullDefinition: ref})
|
return index.SearchIndexForReferenceByReference(&Reference{FullDefinition: ref})
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,10 @@ func (index *SpecIndex) extractDefinitionsAndSchemas(schemasNode *yaml.Node, pat
|
|||||||
}
|
}
|
||||||
|
|
||||||
def := fmt.Sprintf("%s%s", pathPrefix, name)
|
def := fmt.Sprintf("%s%s", pathPrefix, name)
|
||||||
|
fullDef := fmt.Sprintf("%s%s", index.specAbsolutePath, def)
|
||||||
|
|
||||||
ref := &Reference{
|
ref := &Reference{
|
||||||
|
FullDefinition: fullDef,
|
||||||
Definition: def,
|
Definition: def,
|
||||||
Name: name,
|
Name: name,
|
||||||
Node: schema,
|
Node: schema,
|
||||||
@@ -278,6 +281,13 @@ func (index *SpecIndex) scanOperationParams(params []*yaml.Node, pathItemNode *y
|
|||||||
|
|
||||||
paramRefName := param.Content[1].Value
|
paramRefName := param.Content[1].Value
|
||||||
paramRef := index.allMappedRefs[paramRefName]
|
paramRef := index.allMappedRefs[paramRefName]
|
||||||
|
if paramRef == nil {
|
||||||
|
// could be in the rolodex
|
||||||
|
ref := index.SearchIndexForReference(paramRefName)
|
||||||
|
if ref != nil {
|
||||||
|
paramRef = ref
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if index.paramOpRefs[pathItemNode.Value] == nil {
|
if index.paramOpRefs[pathItemNode.Value] == nil {
|
||||||
index.paramOpRefs[pathItemNode.Value] = make(map[string]map[string][]*Reference)
|
index.paramOpRefs[pathItemNode.Value] = make(map[string]map[string][]*Reference)
|
||||||
|
|||||||
Reference in New Issue
Block a user