mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 12:37:49 +00:00
Every `Build()` method now requires a `context.Context`. This is so the rolodex knows where to resolve from when locating relative links. Without knowing where we are, there is no way to resolve anything. This new mechanism allows the model to recurse across as many files as required to locate references, without loosing track of where we are in the process. Signed-off-by: quobix <dave@quobix.com>
197 lines
5.0 KiB
Go
197 lines
5.0 KiB
Go
// Copyright 2023 Princess B33f Heavy Industries / Dave Shanley
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package index
|
|
|
|
import (
|
|
"github.com/stretchr/testify/assert"
|
|
"gopkg.in/yaml.v3"
|
|
"os"
|
|
"testing"
|
|
)
|
|
|
|
func TestSpecIndex_performExternalLookup(t *testing.T) {
|
|
yml := `{
|
|
"openapi": "3.1.0",
|
|
"paths": [
|
|
{"/": {
|
|
"get": {}
|
|
}}
|
|
]
|
|
}`
|
|
var rootNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(yml), &rootNode)
|
|
|
|
c := CreateOpenAPIIndexConfig()
|
|
index := NewSpecIndexWithConfig(&rootNode, c)
|
|
assert.Len(t, index.GetPathsNode().Content, 1)
|
|
}
|
|
|
|
func TestSpecIndex_CheckCircularIndex(t *testing.T) {
|
|
|
|
cFile := "../test_specs/first.yaml"
|
|
yml, _ := os.ReadFile(cFile)
|
|
var rootNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(yml), &rootNode)
|
|
|
|
cf := CreateOpenAPIIndexConfig()
|
|
cf.AvoidCircularReferenceCheck = true
|
|
cf.BasePath = "../test_specs"
|
|
|
|
rolo := NewRolodex(cf)
|
|
rolo.SetRootNode(&rootNode)
|
|
cf.Rolodex = rolo
|
|
|
|
fsCfg := LocalFSConfig{
|
|
BaseDirectory: cf.BasePath,
|
|
FileFilters: []string{"first.yaml", "second.yaml", "third.yaml", "fourth.yaml"},
|
|
DirFS: os.DirFS(cf.BasePath),
|
|
}
|
|
|
|
fileFS, err := NewLocalFSWithConfig(&fsCfg)
|
|
|
|
assert.NoError(t, err)
|
|
rolo.AddLocalFS(cf.BasePath, fileFS)
|
|
|
|
indexedErr := rolo.IndexTheRolodex()
|
|
rolo.BuildIndexes()
|
|
|
|
assert.NoError(t, indexedErr)
|
|
|
|
index := rolo.GetRootIndex()
|
|
|
|
assert.Nil(t, index.uri)
|
|
|
|
a, _ := index.SearchIndexForReference("second.yaml#/properties/property2")
|
|
b, _ := index.SearchIndexForReference("second.yaml")
|
|
c, _ := index.SearchIndexForReference("fourth.yaml")
|
|
|
|
assert.NotNil(t, a)
|
|
assert.NotNil(t, b)
|
|
assert.Nil(t, c)
|
|
}
|
|
|
|
func TestSpecIndex_performExternalLookup_invalidURL(t *testing.T) {
|
|
yml := `openapi: 3.1.0
|
|
components:
|
|
schemas:
|
|
thing:
|
|
properties:
|
|
thong:
|
|
$ref: 'httpssss://not-gonna-work.com'`
|
|
var rootNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(yml), &rootNode)
|
|
|
|
c := CreateOpenAPIIndexConfig()
|
|
index := NewSpecIndexWithConfig(&rootNode, c)
|
|
assert.Len(t, index.GetReferenceIndexErrors(), 1)
|
|
}
|
|
|
|
func TestSpecIndex_FindComponentInRoot(t *testing.T) {
|
|
yml := `openapi: 3.1.0
|
|
components:
|
|
schemas:
|
|
thing:
|
|
properties:
|
|
thong: hi!`
|
|
var rootNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(yml), &rootNode)
|
|
|
|
c := CreateOpenAPIIndexConfig()
|
|
index := NewSpecIndexWithConfig(&rootNode, c)
|
|
|
|
thing := index.FindComponentInRoot("#/$splish/$.../slash#$///./")
|
|
assert.Nil(t, thing)
|
|
assert.Len(t, index.GetReferenceIndexErrors(), 0)
|
|
}
|
|
|
|
func TestSpecIndex_LocateRemoteDocsWithRemoteURLHandler(t *testing.T) {
|
|
|
|
// This test will push the index to do try and locate remote references that use relative references
|
|
spec := `openapi: 3.0.2
|
|
info:
|
|
title: Test
|
|
version: 1.0.0
|
|
paths:
|
|
/test:
|
|
get:
|
|
parameters:
|
|
- $ref: "https://schemas.opengis.net/ogcapi/features/part2/1.0/openapi/ogcapi-features-2.yaml#/components/parameters/crs"`
|
|
|
|
var rootNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(spec), &rootNode)
|
|
|
|
// create a new config that allows remote lookups.
|
|
cf := &SpecIndexConfig{}
|
|
cf.AllowRemoteLookup = true
|
|
cf.AvoidCircularReferenceCheck = true
|
|
|
|
// 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, _ := NewRemoteFSWithConfig(cf)
|
|
|
|
// add remote filesystem
|
|
rolo.AddRemoteFS("", remoteFS)
|
|
|
|
// index the rolodex.
|
|
indexedErr := rolo.IndexTheRolodex()
|
|
|
|
assert.NoError(t, indexedErr)
|
|
|
|
index := rolo.GetRootIndex()
|
|
|
|
// extract crs param from index
|
|
crsParam := index.GetMappedReferences()["https://schemas.opengis.net/ogcapi/features/part2/1.0/openapi/ogcapi-features-2.yaml#/components/parameters/crs"]
|
|
assert.NotNil(t, crsParam)
|
|
assert.True(t, crsParam.IsRemote)
|
|
assert.Equal(t, "crs", crsParam.Node.Content[1].Value)
|
|
assert.Equal(t, "query", crsParam.Node.Content[3].Value)
|
|
assert.Equal(t, "form", crsParam.Node.Content[9].Value)
|
|
}
|
|
|
|
func TestSpecIndex_LocateRemoteDocsWithMalformedEscapedCharacters(t *testing.T) {
|
|
spec := `openapi: 3.0.2
|
|
info:
|
|
title: Test
|
|
version: 1.0.0
|
|
paths:
|
|
/test:
|
|
get:
|
|
parameters:
|
|
- $ref: "https://petstore3.swagger.io/api/v3/openapi.yaml#/paths/~1pet~1%$petId%7D/get/parameters"`
|
|
|
|
var rootNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(spec), &rootNode)
|
|
|
|
c := CreateOpenAPIIndexConfig()
|
|
|
|
index := NewSpecIndexWithConfig(&rootNode, c)
|
|
assert.Len(t, index.GetReferenceIndexErrors(), 1)
|
|
assert.Equal(t, "component '#/paths/~1pet~1%$petId%7D/get/parameters' does not exist in the specification", index.GetReferenceIndexErrors()[0].Error())
|
|
}
|
|
|
|
func TestSpecIndex_LocateRemoteDocsWithEscapedCharacters(t *testing.T) {
|
|
spec := `openapi: 3.0.2
|
|
info:
|
|
title: Test
|
|
version: 1.0.0
|
|
paths:
|
|
/test:
|
|
get:
|
|
parameters:
|
|
- $ref: "https://petstore3.swagger.io/api/v3/openapi.yaml#/paths/~1pet~1%7BpetId%7D/get/parameters"`
|
|
|
|
var rootNode yaml.Node
|
|
_ = yaml.Unmarshal([]byte(spec), &rootNode)
|
|
|
|
c := CreateOpenAPIIndexConfig()
|
|
|
|
index := NewSpecIndexWithConfig(&rootNode, c)
|
|
assert.Len(t, index.GetReferenceIndexErrors(), 1)
|
|
}
|