mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-10 04:20:24 +00:00
more coverage, bumping up rolodex coverage
fixing small glitches now as we go. Signed-off-by: quobix <dave@quobix.com>
This commit is contained in:
@@ -771,3 +771,10 @@ components:
|
|||||||
assert.Len(t, resolver.GetIgnoredCircularPolyReferences(), 1)
|
assert.Len(t, resolver.GetIgnoredCircularPolyReferences(), 1)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolver_isInfiniteCircularDep_NoRef(t *testing.T) {
|
||||||
|
resolver := NewResolver(nil)
|
||||||
|
a, b := resolver.isInfiniteCircularDependency(nil, nil, nil)
|
||||||
|
assert.False(t, a)
|
||||||
|
assert.Nil(t, b)
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ type Rolodex struct {
|
|||||||
remoteFS map[string]fs.FS
|
remoteFS map[string]fs.FS
|
||||||
indexed bool
|
indexed bool
|
||||||
built bool
|
built bool
|
||||||
|
manualBuilt bool
|
||||||
resolved bool
|
resolved bool
|
||||||
circChecked bool
|
circChecked bool
|
||||||
indexConfig *SpecIndexConfig
|
indexConfig *SpecIndexConfig
|
||||||
@@ -467,7 +468,7 @@ func (r *Rolodex) Resolve() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rolodex) BuildIndexes() {
|
func (r *Rolodex) BuildIndexes() {
|
||||||
if r.built {
|
if r.manualBuilt {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, idx := range r.indexes {
|
for _, idx := range r.indexes {
|
||||||
@@ -476,7 +477,7 @@ func (r *Rolodex) BuildIndexes() {
|
|||||||
if r.rootIndex != nil {
|
if r.rootIndex != nil {
|
||||||
r.rootIndex.BuildIndex()
|
r.rootIndex.BuildIndex()
|
||||||
}
|
}
|
||||||
r.built = true
|
r.manualBuilt = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rolodex) Open(location string) (RolodexFile, error) {
|
func (r *Rolodex) Open(location string) (RolodexFile, error) {
|
||||||
@@ -522,7 +523,6 @@ func (r *Rolodex) Open(location string) (RolodexFile, error) {
|
|||||||
}
|
}
|
||||||
// check if this is a native rolodex FS, then the work is done.
|
// check if this is a native rolodex FS, then the work is done.
|
||||||
if lrf, ok := interface{}(f).(*localRolodexFile); ok {
|
if lrf, ok := interface{}(f).(*localRolodexFile); ok {
|
||||||
|
|
||||||
if lf, ko := interface{}(lrf.f).(*LocalFile); ko {
|
if lf, ko := interface{}(lrf.f).(*LocalFile); ko {
|
||||||
localFile = lf
|
localFile = lf
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package index
|
|||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@@ -29,6 +30,17 @@ func TestRolodex_NewRolodex(t *testing.T) {
|
|||||||
assert.Len(t, rolo.GetCaughtErrors(), 0)
|
assert.Len(t, rolo.GetCaughtErrors(), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRolodex_NoFS(t *testing.T) {
|
||||||
|
|
||||||
|
rolo := NewRolodex(CreateOpenAPIIndexConfig())
|
||||||
|
rf, err := rolo.Open("spec.yaml")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, "rolodex has no file systems configured, cannot open 'spec.yaml'. "+
|
||||||
|
"Add a BaseURL or BasePath to your configuration so the rolodex knows how to resolve references", err.Error())
|
||||||
|
assert.Nil(t, rf)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestRolodex_LocalNativeFS(t *testing.T) {
|
func TestRolodex_LocalNativeFS(t *testing.T) {
|
||||||
|
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
@@ -76,6 +88,73 @@ func TestRolodex_LocalNonNativeFS(t *testing.T) {
|
|||||||
assert.Equal(t, "hip", f.GetContent())
|
assert.Equal(t, "hip", f.GetContent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type test_badfs struct {
|
||||||
|
ok bool
|
||||||
|
offset int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *test_badfs) Open(v string) (fs.File, error) {
|
||||||
|
ok := false
|
||||||
|
if v != "/" {
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
return &test_badfs{ok: ok}, nil
|
||||||
|
}
|
||||||
|
func (t *test_badfs) Stat() (fs.FileInfo, error) {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
func (t *test_badfs) Read(b []byte) (int, error) {
|
||||||
|
if t.ok {
|
||||||
|
if t.offset >= int64(len("pizza")) {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
if t.offset < 0 {
|
||||||
|
return 0, &fs.PathError{Op: "read", Path: "lemons", Err: fs.ErrInvalid}
|
||||||
|
}
|
||||||
|
n := copy(b, "pizza"[t.offset:])
|
||||||
|
t.offset += int64(n)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, os.ErrNotExist
|
||||||
|
}
|
||||||
|
func (t *test_badfs) Close() error {
|
||||||
|
return os.ErrNotExist
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodex_LocalNonNativeFS_BadRead(t *testing.T) {
|
||||||
|
|
||||||
|
t.Parallel()
|
||||||
|
testFS := &test_badfs{}
|
||||||
|
|
||||||
|
baseDir := ""
|
||||||
|
|
||||||
|
rolo := NewRolodex(CreateOpenAPIIndexConfig())
|
||||||
|
rolo.AddLocalFS(baseDir, testFS)
|
||||||
|
|
||||||
|
f, rerr := rolo.Open("/")
|
||||||
|
assert.Nil(t, f)
|
||||||
|
assert.Error(t, rerr)
|
||||||
|
assert.Equal(t, "file does not exist", rerr.Error())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodex_LocalNonNativeFS_BadStat(t *testing.T) {
|
||||||
|
|
||||||
|
t.Parallel()
|
||||||
|
testFS := &test_badfs{}
|
||||||
|
|
||||||
|
baseDir := ""
|
||||||
|
|
||||||
|
rolo := NewRolodex(CreateOpenAPIIndexConfig())
|
||||||
|
rolo.AddLocalFS(baseDir, testFS)
|
||||||
|
|
||||||
|
f, rerr := rolo.Open("spec.yaml")
|
||||||
|
assert.Nil(t, f)
|
||||||
|
assert.Error(t, rerr)
|
||||||
|
assert.Equal(t, "invalid argument", rerr.Error())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestRolodex_rolodexFileTests(t *testing.T) {
|
func TestRolodex_rolodexFileTests(t *testing.T) {
|
||||||
r := &rolodexFile{}
|
r := &rolodexFile{}
|
||||||
assert.Equal(t, "", r.Name())
|
assert.Equal(t, "", r.Name())
|
||||||
@@ -323,19 +402,19 @@ components:
|
|||||||
func test_rolodexDeepRefServer(a, b, c, d, e []byte) *httptest.Server {
|
func test_rolodexDeepRefServer(a, b, c, d, e []byte) *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) {
|
||||||
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() == "/first.yaml" {
|
if strings.HasSuffix(req.URL.String(), "/first.yaml") {
|
||||||
_, _ = rw.Write(a)
|
_, _ = rw.Write(a)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.URL.String() == "/second.yaml" {
|
if strings.HasSuffix(req.URL.String(), "/second.yaml") {
|
||||||
_, _ = rw.Write(b)
|
_, _ = rw.Write(b)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.URL.String() == "/third.yaml" {
|
if strings.HasSuffix(req.URL.String(), "/third.yaml") {
|
||||||
_, _ = rw.Write(c)
|
_, _ = rw.Write(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.URL.String() == "/fourth.yaml" {
|
if strings.HasSuffix(req.URL.String(), "/fourth.yaml") {
|
||||||
_, _ = rw.Write(d)
|
_, _ = rw.Write(d)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -362,7 +441,7 @@ components:
|
|||||||
type: "object"
|
type: "object"
|
||||||
oneOf:
|
oneOf:
|
||||||
items:
|
items:
|
||||||
$ref: "second.yaml#/components/schemas/CircleTest"
|
$ref: "second_a.yaml#/components/schemas/CircleTest"
|
||||||
required:
|
required:
|
||||||
- "name"
|
- "name"
|
||||||
- "children"
|
- "children"
|
||||||
@@ -405,10 +484,10 @@ components:
|
|||||||
var rootNode yaml.Node
|
var rootNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(first), &rootNode)
|
_ = yaml.Unmarshal([]byte(first), &rootNode)
|
||||||
|
|
||||||
_ = os.WriteFile("second.yaml", []byte(second), 0644)
|
_ = os.WriteFile("second_a.yaml", []byte(second), 0644)
|
||||||
_ = os.WriteFile("first.yaml", []byte(first), 0644)
|
_ = os.WriteFile("first_a.yaml", []byte(first), 0644)
|
||||||
defer os.Remove("first.yaml")
|
defer os.Remove("first_a.yaml")
|
||||||
defer os.Remove("second.yaml")
|
defer os.Remove("second_a.yaml")
|
||||||
|
|
||||||
cf := CreateOpenAPIIndexConfig()
|
cf := CreateOpenAPIIndexConfig()
|
||||||
cf.IgnorePolymorphicCircularReferences = true
|
cf.IgnorePolymorphicCircularReferences = true
|
||||||
@@ -420,8 +499,200 @@ components:
|
|||||||
BaseDirectory: baseDir,
|
BaseDirectory: baseDir,
|
||||||
DirFS: os.DirFS(baseDir),
|
DirFS: os.DirFS(baseDir),
|
||||||
FileFilters: []string{
|
FileFilters: []string{
|
||||||
"first.yaml",
|
"first_a.yaml",
|
||||||
"second.yaml",
|
"second_a.yaml",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fileFS, err := NewLocalFSWithConfig(fsCfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rolodex.AddLocalFS(baseDir, fileFS)
|
||||||
|
rolodex.SetRootNode(&rootNode)
|
||||||
|
|
||||||
|
err = rolodex.IndexTheRolodex()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, rolodex.GetCaughtErrors(), 0)
|
||||||
|
|
||||||
|
// multiple loops across two files
|
||||||
|
assert.Len(t, rolodex.GetIgnoredCircularReferences(), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodex_IndexCircularLookup_PolyItems_LocalLoop_BuildIndexesPost(t *testing.T) {
|
||||||
|
|
||||||
|
first := `openapi: 3.1.0
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
CircleTest:
|
||||||
|
type: "object"
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: "string"
|
||||||
|
children:
|
||||||
|
type: "object"
|
||||||
|
oneOf:
|
||||||
|
items:
|
||||||
|
$ref: "second_d.yaml#/components/schemas/CircleTest"
|
||||||
|
required:
|
||||||
|
- "name"
|
||||||
|
- "children"
|
||||||
|
StartTest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- muffins
|
||||||
|
properties:
|
||||||
|
muffins:
|
||||||
|
type: object
|
||||||
|
anyOf:
|
||||||
|
- $ref: "#/components/schemas/CircleTest"`
|
||||||
|
|
||||||
|
second := `openapi: 3.1.0
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
CircleTest:
|
||||||
|
type: "object"
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: "string"
|
||||||
|
children:
|
||||||
|
type: "object"
|
||||||
|
oneOf:
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/CircleTest"
|
||||||
|
required:
|
||||||
|
- "name"
|
||||||
|
- "children"
|
||||||
|
StartTest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- muffins
|
||||||
|
properties:
|
||||||
|
muffins:
|
||||||
|
type: object
|
||||||
|
anyOf:
|
||||||
|
- $ref: "#/components/schemas/CircleTest"`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(first), &rootNode)
|
||||||
|
|
||||||
|
_ = os.WriteFile("second_d.yaml", []byte(second), 0644)
|
||||||
|
_ = os.WriteFile("first_d.yaml", []byte(first), 0644)
|
||||||
|
defer os.Remove("first_d.yaml")
|
||||||
|
defer os.Remove("second_d.yaml")
|
||||||
|
|
||||||
|
cf := CreateOpenAPIIndexConfig()
|
||||||
|
cf.IgnorePolymorphicCircularReferences = true
|
||||||
|
cf.AvoidBuildIndex = true
|
||||||
|
rolodex := NewRolodex(cf)
|
||||||
|
|
||||||
|
baseDir := "."
|
||||||
|
|
||||||
|
fsCfg := &LocalFSConfig{
|
||||||
|
BaseDirectory: baseDir,
|
||||||
|
DirFS: os.DirFS(baseDir),
|
||||||
|
FileFilters: []string{
|
||||||
|
"first_d.yaml",
|
||||||
|
"second_d.yaml",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fileFS, err := NewLocalFSWithConfig(fsCfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rolodex.AddLocalFS(baseDir, fileFS)
|
||||||
|
rolodex.SetRootNode(&rootNode)
|
||||||
|
|
||||||
|
err = rolodex.IndexTheRolodex()
|
||||||
|
rolodex.BuildIndexes()
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, rolodex.GetCaughtErrors(), 0)
|
||||||
|
|
||||||
|
// multiple loops across two files
|
||||||
|
assert.Len(t, rolodex.GetIgnoredCircularReferences(), 1)
|
||||||
|
|
||||||
|
// trigger a rebuild, should do nothing.
|
||||||
|
rolodex.BuildIndexes()
|
||||||
|
assert.Len(t, rolodex.GetCaughtErrors(), 0)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodex_IndexCircularLookup_ArrayItems_LocalLoop_WithFiles(t *testing.T) {
|
||||||
|
|
||||||
|
first := `openapi: 3.1.0
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
CircleTest:
|
||||||
|
type: "object"
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: "string"
|
||||||
|
children:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: "second_b.yaml#/components/schemas/CircleTest"
|
||||||
|
required:
|
||||||
|
- "name"
|
||||||
|
- "children"
|
||||||
|
StartTest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- muffins
|
||||||
|
properties:
|
||||||
|
muffins:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/CircleTest"`
|
||||||
|
|
||||||
|
second := `openapi: 3.1.0
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
CircleTest:
|
||||||
|
type: "object"
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: "string"
|
||||||
|
children:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/CircleTest"
|
||||||
|
required:
|
||||||
|
- "name"
|
||||||
|
- "children"
|
||||||
|
StartTest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- muffins
|
||||||
|
properties:
|
||||||
|
muffins:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/CircleTest"`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(first), &rootNode)
|
||||||
|
|
||||||
|
_ = os.WriteFile("second_b.yaml", []byte(second), 0644)
|
||||||
|
_ = os.WriteFile("first_b.yaml", []byte(first), 0644)
|
||||||
|
defer os.Remove("first_b.yaml")
|
||||||
|
defer os.Remove("second_b.yaml")
|
||||||
|
|
||||||
|
cf := CreateOpenAPIIndexConfig()
|
||||||
|
cf.IgnoreArrayCircularReferences = true
|
||||||
|
rolodex := NewRolodex(cf)
|
||||||
|
|
||||||
|
baseDir := "."
|
||||||
|
|
||||||
|
fsCfg := &LocalFSConfig{
|
||||||
|
BaseDirectory: baseDir,
|
||||||
|
DirFS: os.DirFS(baseDir),
|
||||||
|
FileFilters: []string{
|
||||||
|
"first_b.yaml",
|
||||||
|
"second_b.yaml",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,12 +831,12 @@ components:
|
|||||||
type: object
|
type: object
|
||||||
allOf:
|
allOf:
|
||||||
items:
|
items:
|
||||||
$ref: "third.yaml"
|
$ref: "third_c.yaml"
|
||||||
boop:
|
boop:
|
||||||
type: object
|
type: object
|
||||||
allOf:
|
allOf:
|
||||||
items:
|
items:
|
||||||
$ref: "$PWD/third.yaml"
|
$ref: "$PWD/third_c.yaml"
|
||||||
loop:
|
loop:
|
||||||
type: object
|
type: object
|
||||||
oneOf:
|
oneOf:
|
||||||
@@ -595,20 +866,20 @@ components:
|
|||||||
muffins:
|
muffins:
|
||||||
type: object
|
type: object
|
||||||
anyOf:
|
anyOf:
|
||||||
- $ref: "second.yaml#/components/schemas/CircleTest"
|
- $ref: "second_c.yaml#/components/schemas/CircleTest"
|
||||||
- $ref: "$PWD/third.yaml"`
|
- $ref: "$PWD/third_c.yaml"`
|
||||||
|
|
||||||
var rootNode yaml.Node
|
var rootNode yaml.Node
|
||||||
cws, _ := os.Getwd()
|
cws, _ := os.Getwd()
|
||||||
|
|
||||||
_ = yaml.Unmarshal([]byte(strings.ReplaceAll(first, "$PWD", cws)), &rootNode)
|
_ = yaml.Unmarshal([]byte(strings.ReplaceAll(first, "$PWD", cws)), &rootNode)
|
||||||
_ = os.WriteFile("second.yaml", []byte(strings.ReplaceAll(second, "$PWD", cws)), 0644)
|
_ = os.WriteFile("second_c.yaml", []byte(strings.ReplaceAll(second, "$PWD", cws)), 0644)
|
||||||
_ = os.WriteFile("first.yaml", []byte(strings.ReplaceAll(first, "$PWD", cws)), 0644)
|
_ = os.WriteFile("first_c.yaml", []byte(strings.ReplaceAll(first, "$PWD", cws)), 0644)
|
||||||
_ = os.WriteFile("third.yaml", []byte(third), 0644)
|
_ = os.WriteFile("third_c.yaml", []byte(third), 0644)
|
||||||
|
|
||||||
defer os.Remove("first.yaml")
|
defer os.Remove("first_c.yaml")
|
||||||
defer os.Remove("second.yaml")
|
defer os.Remove("second_c.yaml")
|
||||||
defer os.Remove("third.yaml")
|
defer os.Remove("third_c.yaml")
|
||||||
|
|
||||||
cf := CreateOpenAPIIndexConfig()
|
cf := CreateOpenAPIIndexConfig()
|
||||||
cf.IgnorePolymorphicCircularReferences = true
|
cf.IgnorePolymorphicCircularReferences = true
|
||||||
@@ -620,9 +891,9 @@ components:
|
|||||||
BaseDirectory: baseDir,
|
BaseDirectory: baseDir,
|
||||||
DirFS: os.DirFS(baseDir),
|
DirFS: os.DirFS(baseDir),
|
||||||
FileFilters: []string{
|
FileFilters: []string{
|
||||||
"first.yaml",
|
"first_c.yaml",
|
||||||
"second.yaml",
|
"second_c.yaml",
|
||||||
"third.yaml",
|
"third_c.yaml",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,6 +913,100 @@ components:
|
|||||||
assert.Len(t, rolodex.GetIgnoredCircularReferences(), 1)
|
assert.Len(t, rolodex.GetIgnoredCircularReferences(), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRolodex_TestDropDownToRemoteFS_CatchErrors(t *testing.T) {
|
||||||
|
|
||||||
|
fourth := `type: "object"
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: "string"
|
||||||
|
children:
|
||||||
|
type: "object"`
|
||||||
|
|
||||||
|
third := `type: "object"
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
$ref: "http://the-space-race-is-all-about-space-and-time-dot.com/fourth.yaml"`
|
||||||
|
|
||||||
|
second := `openapi: 3.1.0
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
CircleTest:
|
||||||
|
type: "object"
|
||||||
|
properties:
|
||||||
|
bing:
|
||||||
|
$ref: "not_found.yaml"
|
||||||
|
name:
|
||||||
|
type: "string"
|
||||||
|
children:
|
||||||
|
type: "object"
|
||||||
|
anyOf:
|
||||||
|
- $ref: "third.yaml"
|
||||||
|
required:
|
||||||
|
- "name"
|
||||||
|
- "children"`
|
||||||
|
|
||||||
|
first := `openapi: 3.1.0
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
StartTest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- muffins
|
||||||
|
properties:
|
||||||
|
muffins:
|
||||||
|
$ref: "second_e.yaml#/components/schemas/CircleTest"`
|
||||||
|
|
||||||
|
cwd, _ := os.Getwd()
|
||||||
|
|
||||||
|
_ = os.WriteFile("third_e.yaml", []byte(strings.ReplaceAll(third, "$PWD", cwd)), 0644)
|
||||||
|
_ = os.WriteFile("second_e.yaml", []byte(second), 0644)
|
||||||
|
_ = os.WriteFile("first_e.yaml", []byte(first), 0644)
|
||||||
|
_ = os.WriteFile("fourth_e.yaml", []byte(fourth), 0644)
|
||||||
|
defer os.Remove("first_e.yaml")
|
||||||
|
defer os.Remove("second_e.yaml")
|
||||||
|
defer os.Remove("third_e.yaml")
|
||||||
|
defer os.Remove("fourth_e.yaml")
|
||||||
|
|
||||||
|
baseDir := "."
|
||||||
|
|
||||||
|
fsCfg := &LocalFSConfig{
|
||||||
|
BaseDirectory: baseDir,
|
||||||
|
DirFS: os.DirFS(baseDir),
|
||||||
|
FileFilters: []string{
|
||||||
|
"first_e.yaml",
|
||||||
|
"second_e.yaml",
|
||||||
|
"third_e.yaml",
|
||||||
|
"fourth_e.yaml",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fileFS, err := NewLocalFSWithConfig(fsCfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cf := CreateOpenAPIIndexConfig()
|
||||||
|
cf.BasePath = baseDir
|
||||||
|
cf.IgnorePolymorphicCircularReferences = true
|
||||||
|
rolodex := NewRolodex(cf)
|
||||||
|
rolodex.AddLocalFS(baseDir, fileFS)
|
||||||
|
|
||||||
|
srv := test_rolodexDeepRefServer([]byte(first), []byte(second),
|
||||||
|
[]byte(strings.ReplaceAll(third, "$PWD", cwd)), []byte(fourth), nil)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
u, _ := url.Parse(srv.URL)
|
||||||
|
cf.BaseURL = u
|
||||||
|
remoteFS, rErr := NewRemoteFSWithConfig(cf)
|
||||||
|
assert.NoError(t, rErr)
|
||||||
|
|
||||||
|
rolodex.AddRemoteFS(srv.URL, remoteFS)
|
||||||
|
|
||||||
|
err = rolodex.IndexTheRolodex()
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Len(t, rolodex.GetCaughtErrors(), 2)
|
||||||
|
}
|
||||||
|
|
||||||
func TestRolodex_IndexCircularLookup_LookupHttpNoBaseURL(t *testing.T) {
|
func TestRolodex_IndexCircularLookup_LookupHttpNoBaseURL(t *testing.T) {
|
||||||
|
|
||||||
first := `openapi: 3.1.0
|
first := `openapi: 3.1.0
|
||||||
@@ -872,6 +1237,76 @@ components:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRolodex_CircularReferencesPolyIgnored_Resolve(t *testing.T) {
|
||||||
|
|
||||||
|
var d = `openapi: 3.1.0
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
bingo:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
bango:
|
||||||
|
$ref: "#/components/schemas/ProductCategory"
|
||||||
|
ProductCategory:
|
||||||
|
type: "object"
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: "string"
|
||||||
|
children:
|
||||||
|
type: "object"
|
||||||
|
items:
|
||||||
|
anyOf:
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/ProductCategory"
|
||||||
|
description: "Array of sub-categories in the same format."
|
||||||
|
required:
|
||||||
|
- "name"
|
||||||
|
- "children"`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(d), &rootNode)
|
||||||
|
|
||||||
|
c := CreateClosedAPIIndexConfig()
|
||||||
|
c.IgnorePolymorphicCircularReferences = true
|
||||||
|
c.AvoidCircularReferenceCheck = true
|
||||||
|
rolo := NewRolodex(c)
|
||||||
|
rolo.SetRootNode(&rootNode)
|
||||||
|
_ = rolo.IndexTheRolodex()
|
||||||
|
assert.NotNil(t, rolo.GetRootIndex())
|
||||||
|
rolo.Resolve()
|
||||||
|
assert.Len(t, rolo.GetIgnoredCircularReferences(), 1)
|
||||||
|
assert.Len(t, rolo.GetCaughtErrors(), 0)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodex_CircularReferencesPostCheck(t *testing.T) {
|
||||||
|
|
||||||
|
var d = `openapi: 3.1.0
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
bingo:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
bango:
|
||||||
|
$ref: "#/components/schemas/bingo"
|
||||||
|
required:
|
||||||
|
- bango`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(d), &rootNode)
|
||||||
|
|
||||||
|
c := CreateClosedAPIIndexConfig()
|
||||||
|
c.AvoidCircularReferenceCheck = true
|
||||||
|
rolo := NewRolodex(c)
|
||||||
|
rolo.SetRootNode(&rootNode)
|
||||||
|
_ = rolo.IndexTheRolodex()
|
||||||
|
assert.NotNil(t, rolo.GetRootIndex())
|
||||||
|
rolo.CheckForCircularReferences()
|
||||||
|
assert.Len(t, rolo.GetIgnoredCircularReferences(), 0)
|
||||||
|
assert.Len(t, rolo.GetCaughtErrors(), 1)
|
||||||
|
assert.Len(t, rolo.GetRootIndex().GetResolver().GetCircularErrors(), 1)
|
||||||
|
}
|
||||||
|
|
||||||
func TestRolodex_CircularReferencesArrayIgnored(t *testing.T) {
|
func TestRolodex_CircularReferencesArrayIgnored(t *testing.T) {
|
||||||
|
|
||||||
var d = `openapi: 3.1.0
|
var d = `openapi: 3.1.0
|
||||||
@@ -905,6 +1340,39 @@ components:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRolodex_CircularReferencesArrayIgnored_Resolve(t *testing.T) {
|
||||||
|
|
||||||
|
var d = `openapi: 3.1.0
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
ProductCategory:
|
||||||
|
type: "object"
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: "string"
|
||||||
|
children:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/ProductCategory"
|
||||||
|
description: "Array of sub-categories in the same format."
|
||||||
|
required:
|
||||||
|
- "name"
|
||||||
|
- "children"`
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(d), &rootNode)
|
||||||
|
|
||||||
|
c := CreateClosedAPIIndexConfig()
|
||||||
|
c.IgnoreArrayCircularReferences = true
|
||||||
|
rolo := NewRolodex(c)
|
||||||
|
rolo.SetRootNode(&rootNode)
|
||||||
|
_ = rolo.IndexTheRolodex()
|
||||||
|
rolo.Resolve()
|
||||||
|
assert.Len(t, rolo.GetIgnoredCircularReferences(), 1)
|
||||||
|
assert.Len(t, rolo.GetCaughtErrors(), 0)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestRolodex_CircularReferencesArrayIgnored_PostCheck(t *testing.T) {
|
func TestRolodex_CircularReferencesArrayIgnored_PostCheck(t *testing.T) {
|
||||||
|
|
||||||
var d = `openapi: 3.1.0
|
var d = `openapi: 3.1.0
|
||||||
|
|||||||
Reference in New Issue
Block a user