mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-09 12:37:49 +00:00
Bumping coverage on schema to 100%
I think it should be pretty much bullet proof at the moment (until the next failure). Also added external index lookups from main index for external docs. found this bug after refining lookups in schemas.
This commit is contained in:
@@ -70,8 +70,18 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
|
||||
func (s *Schema) BuildLevel(root *yaml.Node, idx *index.SpecIndex, level int) error {
|
||||
level++
|
||||
if level > 10 {
|
||||
return nil // we're done, son! too fricken deep.
|
||||
if level > 30 {
|
||||
return fmt.Errorf("schema is too nested to continue: %d levels deep, is too deep", level) // we're done, son! too fricken deep.
|
||||
}
|
||||
|
||||
if h, _, _ := utils.IsNodeRefValue(root); h {
|
||||
ref := low.LocateRefNode(root, idx)
|
||||
if ref != nil {
|
||||
root = ref
|
||||
} else {
|
||||
return fmt.Errorf("build schema failed: reference cannot be found: %s, line %d, col %d",
|
||||
root.Content[1].Value, root.Content[1].Line, root.Content[1].Column)
|
||||
}
|
||||
}
|
||||
|
||||
s.extractExtensions(root)
|
||||
@@ -102,10 +112,7 @@ func (s *Schema) BuildLevel(root *yaml.Node, idx *index.SpecIndex, level int) er
|
||||
_, discLabel, discNode := utils.FindKeyNodeFull(DiscriminatorLabel, root.Content)
|
||||
if discNode != nil {
|
||||
var discriminator Discriminator
|
||||
err := low.BuildModel(discNode, &discriminator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = low.BuildModel(discNode, &discriminator)
|
||||
s.Discriminator = low.NodeReference[*Discriminator]{Value: &discriminator, KeyNode: discLabel, ValueNode: discNode}
|
||||
}
|
||||
|
||||
@@ -113,14 +120,8 @@ func (s *Schema) BuildLevel(root *yaml.Node, idx *index.SpecIndex, level int) er
|
||||
_, extDocLabel, extDocNode := utils.FindKeyNodeFull(ExternalDocsLabel, root.Content)
|
||||
if extDocNode != nil {
|
||||
var exDoc ExternalDoc
|
||||
err := low.BuildModel(extDocNode, &exDoc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = exDoc.Build(extDocNode, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = low.BuildModel(extDocNode, &exDoc)
|
||||
_ = exDoc.Build(extDocNode, idx) // throws no errors, can't check for one.
|
||||
s.ExternalDocs = low.NodeReference[*ExternalDoc]{Value: &exDoc, KeyNode: extDocLabel, ValueNode: extDocNode}
|
||||
}
|
||||
|
||||
@@ -128,15 +129,9 @@ func (s *Schema) BuildLevel(root *yaml.Node, idx *index.SpecIndex, level int) er
|
||||
_, xmlLabel, xmlNode := utils.FindKeyNodeFull(XMLLabel, root.Content)
|
||||
if xmlNode != nil {
|
||||
var xml XML
|
||||
err := low.BuildModel(xmlNode, &xml)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = low.BuildModel(xmlNode, &xml)
|
||||
// extract extensions if set.
|
||||
err = xml.Build(xmlNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = xml.Build(xmlNode) // returns no errors, can't check for one.
|
||||
s.XML = low.NodeReference[*XML]{Value: &xml, KeyNode: xmlLabel, ValueNode: xmlNode}
|
||||
}
|
||||
|
||||
@@ -156,15 +151,15 @@ func (s *Schema) BuildLevel(root *yaml.Node, idx *index.SpecIndex, level int) er
|
||||
ref := low.LocateRefNode(prop, idx)
|
||||
if ref != nil {
|
||||
prop = ref
|
||||
} else {
|
||||
return fmt.Errorf("schema properties build failed: cannot find reference %s, line %d, col %d",
|
||||
prop.Content[1].Value, prop.Content[1].Column, prop.Content[1].Line)
|
||||
}
|
||||
}
|
||||
|
||||
var property Schema
|
||||
err := low.BuildModel(prop, &property)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = property.BuildLevel(prop, idx, level)
|
||||
_ = low.BuildModel(prop, &property)
|
||||
err := property.BuildLevel(prop, idx, level)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -181,6 +176,7 @@ func (s *Schema) BuildLevel(root *yaml.Node, idx *index.SpecIndex, level int) er
|
||||
KeyNode: propLabel,
|
||||
ValueNode: propsNode,
|
||||
}
|
||||
}
|
||||
|
||||
// extract all sub-schemas
|
||||
var errors []error
|
||||
@@ -233,7 +229,7 @@ func (s *Schema) BuildLevel(root *yaml.Node, idx *index.SpecIndex, level int) er
|
||||
ValueNode: itemsValue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -246,15 +242,27 @@ func buildSchema(schemas *[]low.NodeReference[*Schema], attribute string, rootNo
|
||||
|
||||
_, labelNode, valueNode = utils.FindKeyNodeFull(attribute, rootNode.Content)
|
||||
//wg.Add(1)
|
||||
if valueNode == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if valueNode != nil {
|
||||
var build = func(kn *yaml.Node, vn *yaml.Node) *low.NodeReference[*Schema] {
|
||||
var schema Schema
|
||||
err := low.BuildModel(vn, &schema)
|
||||
if err != nil {
|
||||
*errors = append(*errors, err)
|
||||
|
||||
if h, _, _ := utils.IsNodeRefValue(vn); h {
|
||||
ref := low.LocateRefNode(vn, idx)
|
||||
if ref != nil {
|
||||
vn = ref
|
||||
} else {
|
||||
*errors = append(*errors, fmt.Errorf("build schema failed: reference cannot be found: %s, line %d, col %d",
|
||||
vn.Content[1].Value, vn.Content[1].Line, vn.Content[1].Column))
|
||||
return nil
|
||||
}
|
||||
err = schema.BuildLevel(vn, idx, level)
|
||||
}
|
||||
|
||||
_ = low.BuildModel(vn, &schema)
|
||||
err := schema.BuildLevel(vn, idx, level)
|
||||
if err != nil {
|
||||
*errors = append(*errors, err)
|
||||
return nil
|
||||
@@ -267,6 +275,17 @@ func buildSchema(schemas *[]low.NodeReference[*Schema], attribute string, rootNo
|
||||
}
|
||||
|
||||
if utils.IsNodeMap(valueNode) {
|
||||
if h, _, _ := utils.IsNodeRefValue(valueNode); h {
|
||||
ref := low.LocateRefNode(valueNode, idx)
|
||||
if ref != nil {
|
||||
valueNode = ref
|
||||
} else {
|
||||
*errors = append(*errors, fmt.Errorf("build schema failed: reference cannot be found: %s, line %d, col %d",
|
||||
valueNode.Content[1].Value, valueNode.Content[1].Line, valueNode.Content[1].Column))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
schema := build(labelNode, valueNode)
|
||||
if schema != nil {
|
||||
*schemas = append(*schemas, *schema)
|
||||
@@ -274,6 +293,17 @@ func buildSchema(schemas *[]low.NodeReference[*Schema], attribute string, rootNo
|
||||
}
|
||||
if utils.IsNodeArray(valueNode) {
|
||||
for _, vn := range valueNode.Content {
|
||||
|
||||
if h, _, _ := utils.IsNodeRefValue(vn); h {
|
||||
ref := low.LocateRefNode(vn, idx)
|
||||
if ref != nil {
|
||||
vn = ref
|
||||
} else {
|
||||
*errors = append(*errors, fmt.Errorf("build schema failed: reference cannot be found: %s, line %d, col %d",
|
||||
vn.Content[1].Value, vn.Content[1].Line, vn.Content[1].Column))
|
||||
}
|
||||
}
|
||||
|
||||
schema := build(vn, vn)
|
||||
if schema != nil {
|
||||
*schemas = append(*schemas, *schema)
|
||||
@@ -316,11 +346,8 @@ func ExtractSchema(root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*S
|
||||
|
||||
if schNode != nil {
|
||||
var schema Schema
|
||||
err := low.BuildModel(schNode, &schema)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = schema.Build(schNode, idx)
|
||||
_ = low.BuildModel(schNode, &schema)
|
||||
err := schema.Build(schNode, idx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"testing"
|
||||
@@ -218,3 +219,691 @@ additionalProperties: true `
|
||||
mv = sch.Discriminator.Value.FindMappingValue("pizza")
|
||||
assert.Equal(t, "party", mv.Value)
|
||||
}
|
||||
|
||||
func TestSchema_BuildLevel_TooDeep(t *testing.T) {
|
||||
|
||||
// if you design data models like this, you're doing it fucking wrong. Seriously. why, what is so complex about a model
|
||||
// that it needs to be 30+ levels deep? I have seen this shit in the wild, it's unreadable, un-parsable garbage.
|
||||
yml := `type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
type: object`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
idx := index.NewSpecIndex(&idxNode)
|
||||
|
||||
var n Schema
|
||||
err := low.BuildModel(&idxNode, &n)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = n.Build(idxNode.Content[0], idx)
|
||||
assert.Error(t, err)
|
||||
|
||||
}
|
||||
|
||||
func TestSchema_Build_ErrorAdditionalProps(t *testing.T) {
|
||||
|
||||
yml := `additionalProperties:
|
||||
$ref: #borko`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
idx := index.NewSpecIndex(&idxNode)
|
||||
|
||||
var n Schema
|
||||
err := low.BuildModel(&idxNode, &n)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = n.Build(idxNode.Content[0], idx)
|
||||
assert.Error(t, err)
|
||||
|
||||
}
|
||||
|
||||
func TestSchema_Build_PropsLookup(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
description: this is something
|
||||
type: string`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `type: object
|
||||
properties:
|
||||
aValue:
|
||||
$ref: '#/components/schemas/Something'`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
var n Schema
|
||||
err := n.Build(idxNode.Content[0], idx)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "this is something", n.FindProperty("aValue").Value.Description.Value)
|
||||
|
||||
}
|
||||
|
||||
func TestSchema_Build_PropsLookup_Fail(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
description: this is something
|
||||
type: string`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `type: object
|
||||
properties:
|
||||
aValue:
|
||||
$ref: '#/bork'`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
var n Schema
|
||||
err := n.Build(idxNode.Content[0], idx)
|
||||
assert.Error(t, err)
|
||||
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_Array_Ref(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
type: object
|
||||
description: poly thing
|
||||
properties:
|
||||
polyProp:
|
||||
type: string
|
||||
description: a property
|
||||
example: anything`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `type: object
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Something'
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/Something'
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/Something'
|
||||
not:
|
||||
- $ref: '#/components/schemas/Something'
|
||||
items:
|
||||
- $ref: '#/components/schemas/Something'`
|
||||
|
||||
var sch Schema
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
err := low.BuildModel(&idxNode, &sch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
schErr := sch.Build(idxNode.Content[0], idx)
|
||||
assert.NoError(t, schErr)
|
||||
|
||||
desc := "poly thing"
|
||||
assert.Equal(t, desc, sch.OneOf.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.AnyOf.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.AllOf.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.Not.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.Items.Value[0].Value.Description.Value)
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_Array_Ref_Fail(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
type: object
|
||||
description: poly thing
|
||||
properties:
|
||||
polyProp:
|
||||
type: string
|
||||
description: a property
|
||||
example: anything`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `type: object
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/Missing'
|
||||
oneOf:
|
||||
- $ref: '#/components/schemas/Something'
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/Something'
|
||||
not:
|
||||
- $ref: '#/components/schemas/Something'
|
||||
items:
|
||||
- $ref: '#/components/schemas/Something'`
|
||||
|
||||
var sch Schema
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
err := low.BuildModel(&idxNode, &sch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
schErr := sch.Build(idxNode.Content[0], idx)
|
||||
assert.Error(t, schErr)
|
||||
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_Map_Ref(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
type: object
|
||||
description: poly thing
|
||||
properties:
|
||||
polyProp:
|
||||
type: string
|
||||
description: a property
|
||||
example: anything`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `type: object
|
||||
allOf:
|
||||
$ref: '#/components/schemas/Something'
|
||||
oneOf:
|
||||
$ref: '#/components/schemas/Something'
|
||||
anyOf:
|
||||
$ref: '#/components/schemas/Something'
|
||||
not:
|
||||
$ref: '#/components/schemas/Something'
|
||||
items:
|
||||
$ref: '#/components/schemas/Something'`
|
||||
|
||||
var sch Schema
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
err := low.BuildModel(&idxNode, &sch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
schErr := sch.Build(idxNode.Content[0], idx)
|
||||
assert.NoError(t, schErr)
|
||||
|
||||
desc := "poly thing"
|
||||
assert.Equal(t, desc, sch.OneOf.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.AnyOf.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.AllOf.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.Not.Value[0].Value.Description.Value)
|
||||
assert.Equal(t, desc, sch.Items.Value[0].Value.Description.Value)
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_Map_Ref_Fail(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
type: object
|
||||
description: poly thing
|
||||
properties:
|
||||
polyProp:
|
||||
type: string
|
||||
description: a property
|
||||
example: anything`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `type: object
|
||||
allOf:
|
||||
$ref: '#/components/schemas/Missing'
|
||||
oneOf:
|
||||
$ref: '#/components/schemas/Something'
|
||||
anyOf:
|
||||
$ref: '#/components/schemas/Something'
|
||||
not:
|
||||
$ref: '#/components/schemas/Something'
|
||||
items:
|
||||
$ref: '#/components/schemas/Something'`
|
||||
|
||||
var sch Schema
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
err := low.BuildModel(&idxNode, &sch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
schErr := sch.Build(idxNode.Content[0], idx)
|
||||
assert.Error(t, schErr)
|
||||
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_BorkParent(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
$ref: #borko`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `type: object
|
||||
allOf:
|
||||
$ref: '#/components/schemas/Something'`
|
||||
|
||||
var sch Schema
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
err := low.BuildModel(&idxNode, &sch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
schErr := sch.Build(idxNode.Content[0], idx)
|
||||
assert.Error(t, schErr)
|
||||
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_BorkChild(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
$ref: #borko`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `type: object
|
||||
allOf:
|
||||
$ref: #borko`
|
||||
|
||||
var sch Schema
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
err := low.BuildModel(&idxNode, &sch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
schErr := sch.Build(idxNode.Content[0], idx)
|
||||
assert.Error(t, schErr)
|
||||
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_RefMadness(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
$ref: '#/components/schemas/Else'
|
||||
Else:
|
||||
description: madness`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `type: object
|
||||
allOf:
|
||||
$ref: '#/components/schemas/Something'`
|
||||
|
||||
var sch Schema
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
err := low.BuildModel(&idxNode, &sch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
schErr := sch.Build(idxNode.Content[0], idx)
|
||||
assert.NoError(t, schErr)
|
||||
|
||||
desc := "madness"
|
||||
assert.Equal(t, desc, sch.AllOf.Value[0].Value.Description.Value)
|
||||
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_RefMadnessBork(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
$ref: '#/components/schemas/Else'
|
||||
Else:
|
||||
$ref: #borko`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `type: object
|
||||
allOf:
|
||||
$ref: '#/components/schemas/Something'`
|
||||
|
||||
var sch Schema
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
err := low.BuildModel(&idxNode, &sch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
schErr := sch.Build(idxNode.Content[0], idx)
|
||||
assert.Error(t, schErr)
|
||||
|
||||
}
|
||||
|
||||
func Test_Schema_Polymorphism_RefMadnessIllegal(t *testing.T) {
|
||||
|
||||
// this does not work, but it won't error out.
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
$ref: '#/components/schemas/Else'
|
||||
Else:
|
||||
description: hey!`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `$ref: '#/components/schemas/Something'`
|
||||
|
||||
var sch Schema
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
err := low.BuildModel(&idxNode, &sch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
schErr := sch.Build(idxNode.Content[0], idx)
|
||||
assert.NoError(t, schErr)
|
||||
|
||||
}
|
||||
|
||||
func TestExtractSchema(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
description: this is something
|
||||
type: string`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `schema:
|
||||
type: object
|
||||
properties:
|
||||
aValue:
|
||||
$ref: '#/components/schemas/Something'`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, res.Value)
|
||||
assert.Equal(t, "this is something", res.Value.FindProperty("aValue").Value.Description.Value)
|
||||
}
|
||||
|
||||
func TestExtractSchema_Ref(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
description: this is something
|
||||
type: string`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `schema:
|
||||
$ref: '#/components/schemas/Something'`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, res.Value)
|
||||
assert.Equal(t, "this is something", res.Value.Description.Value)
|
||||
}
|
||||
|
||||
func TestExtractSchema_Ref_Fail(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
description: this is something
|
||||
type: string`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `schema:
|
||||
$ref: '#/components/schemas/Missing'`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
_, err := ExtractSchema(idxNode.Content[0], idx)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestExtractSchema_RefRoot(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
description: this is something
|
||||
type: string`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `$ref: '#/components/schemas/Something'`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, res.Value)
|
||||
assert.Equal(t, "this is something", res.Value.Description.Value)
|
||||
}
|
||||
|
||||
func TestExtractSchema_RefRoot_Fail(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
description: this is something
|
||||
type: string`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `$ref: '#/components/schemas/Missing'`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
_, err := ExtractSchema(idxNode.Content[0], idx)
|
||||
assert.Error(t, err)
|
||||
|
||||
}
|
||||
|
||||
func TestExtractSchema_RefRoot_Child_Fail(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
$ref: #bork`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `$ref: '#/components/schemas/Something'`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
_, err := ExtractSchema(idxNode.Content[0], idx)
|
||||
assert.Error(t, err)
|
||||
|
||||
}
|
||||
|
||||
func TestExtractSchema_DoNothing(t *testing.T) {
|
||||
|
||||
doc := `components:
|
||||
schemas:
|
||||
Something:
|
||||
$ref: #bork`
|
||||
|
||||
var iNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(doc), &iNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&iNode)
|
||||
|
||||
yml := `please: do nothing.`
|
||||
|
||||
var idxNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
||||
assert.Nil(t, res)
|
||||
assert.Nil(t, err)
|
||||
|
||||
}
|
||||
|
||||
@@ -43,6 +43,31 @@ func LocateRefNode(root *yaml.Node, idx *index.SpecIndex) *yaml.Node {
|
||||
idx.GetAllResponses,
|
||||
idx.GetAllSecuritySchemes,
|
||||
}
|
||||
|
||||
// if there are any external indexes being used by remote
|
||||
// documents, then we need to search through them also.
|
||||
externalIndexes := idx.GetAllExternalIndexes()
|
||||
if len(externalIndexes) > 0 {
|
||||
var extCollection []func() map[string]*index.Reference
|
||||
for _, extIndex := range externalIndexes {
|
||||
extCollection = []func() map[string]*index.Reference{
|
||||
extIndex.GetAllSchemas,
|
||||
extIndex.GetMappedReferences,
|
||||
extIndex.GetAllExternalDocuments,
|
||||
extIndex.GetAllParameters,
|
||||
extIndex.GetAllHeaders,
|
||||
extIndex.GetAllCallbacks,
|
||||
extIndex.GetAllLinks,
|
||||
extIndex.GetAllExternalDocuments,
|
||||
extIndex.GetAllExamples,
|
||||
extIndex.GetAllRequestBodies,
|
||||
extIndex.GetAllResponses,
|
||||
extIndex.GetAllSecuritySchemes,
|
||||
}
|
||||
collections = append(collections, extCollection...)
|
||||
}
|
||||
}
|
||||
|
||||
var found map[string]*index.Reference
|
||||
for _, collection := range collections {
|
||||
found = collection()
|
||||
@@ -69,6 +94,16 @@ func LocateRefNode(root *yaml.Node, idx *index.SpecIndex) *yaml.Node {
|
||||
}
|
||||
|
||||
func ExtractObjectRaw[T Buildable[N], N any](root *yaml.Node, idx *index.SpecIndex) (T, error) {
|
||||
|
||||
if h, _, _ := utils.IsNodeRefValue(root); h {
|
||||
ref := LocateRefNode(root, idx)
|
||||
if ref != nil {
|
||||
root = ref
|
||||
} else {
|
||||
return nil, fmt.Errorf("object extraction failed: reference cannot be found: %s, line %d, col %d",
|
||||
root.Content[1].Value, root.Content[1].Line, root.Content[1].Column)
|
||||
}
|
||||
}
|
||||
var n T = new(N)
|
||||
err := BuildModel(root, n)
|
||||
if err != nil {
|
||||
|
||||
@@ -495,6 +495,11 @@ func (index *SpecIndex) GetAllOperationsServers() map[string]map[string][]*Refer
|
||||
return index.opServersRefs
|
||||
}
|
||||
|
||||
// GetAllExternalIndexes will return all indexes for external documents
|
||||
func (index *SpecIndex) GetAllExternalIndexes() map[string]*SpecIndex {
|
||||
return index.externalSpecIndex
|
||||
}
|
||||
|
||||
func (index *SpecIndex) checkPolymorphicNode(name string) (bool, string) {
|
||||
switch name {
|
||||
case "anyOf":
|
||||
|
||||
@@ -13,7 +13,11 @@ var doc *v3.Document
|
||||
func init() {
|
||||
data, _ := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
doc, _ = CreateDocument(info)
|
||||
var err []error
|
||||
doc, err = CreateDocument(info)
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCreateDocument(b *testing.B) {
|
||||
|
||||
Reference in New Issue
Block a user