mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 04:20:11 +00:00
Supercharged test coverage back up to 99.9%
I can't test that one line in the index, so this will do. Now to complete the document for what's changed.
This commit is contained in:
35
datamodel/high/base/security_requirement_test.go
Normal file
35
datamodel/high/base/security_requirement_test.go
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package base
|
||||
|
||||
import (
|
||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewSecurityRequirement(t *testing.T) {
|
||||
|
||||
var cNode yaml.Node
|
||||
|
||||
yml := `pizza:
|
||||
- cheese
|
||||
- tomato`
|
||||
|
||||
_ = yaml.Unmarshal([]byte(yml), &cNode)
|
||||
|
||||
var lowExt lowbase.SecurityRequirement
|
||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowExt)
|
||||
|
||||
_ = lowExt.Build(cNode.Content[0], nil)
|
||||
|
||||
highExt := NewSecurityRequirement(&lowExt)
|
||||
|
||||
assert.Len(t, highExt.Requirements["pizza"], 2)
|
||||
|
||||
wentLow := highExt.GoLow()
|
||||
assert.Len(t, wentLow.Requirements.Value, 1)
|
||||
}
|
||||
@@ -182,10 +182,10 @@ func TestNewSwaggerDocument_Definitions_Responses(t *testing.T) {
|
||||
assert.Len(t, x.Enum, 2)
|
||||
|
||||
wentQuiteLow := y.GoLow()
|
||||
assert.Equal(t, 717, wentQuiteLow.Type.KeyNode.Line)
|
||||
assert.Equal(t, 729, wentQuiteLow.Type.KeyNode.Line)
|
||||
|
||||
wentLowest := x.GoLow()
|
||||
assert.Equal(t, 733, wentLowest.UniqueItems.KeyNode.Line)
|
||||
assert.Equal(t, 745, wentLowest.UniqueItems.KeyNode.Line)
|
||||
}
|
||||
|
||||
func TestNewSwaggerDocument_Definitions(t *testing.T) {
|
||||
@@ -195,7 +195,7 @@ func TestNewSwaggerDocument_Definitions(t *testing.T) {
|
||||
assert.Len(t, highDoc.Definitions.Definitions, 6)
|
||||
|
||||
wentLow := highDoc.Definitions.GoLow()
|
||||
assert.Equal(t, 836, wentLow.FindSchema("User").ValueNode.Line)
|
||||
assert.Equal(t, 848, wentLow.FindSchema("User").ValueNode.Line)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"testing"
|
||||
@@ -19,10 +20,19 @@ func TestSchemaProxy_Build(t *testing.T) {
|
||||
|
||||
err := sch.Build(idxNode.Content[0], nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "3fc9b689459d738f8c88a3a48aa9e33542016b7a4052e001aaa536fca74813cb",
|
||||
low.GenerateHashString(&sch))
|
||||
|
||||
assert.Equal(t, "something", sch.Schema().Description.Value)
|
||||
assert.Empty(t, sch.GetSchemaReference())
|
||||
assert.NotNil(t, sch.GetValueNode())
|
||||
assert.False(t, sch.IsSchemaReference())
|
||||
|
||||
// already rendered, should spit out the same
|
||||
assert.Equal(t, "3fc9b689459d738f8c88a3a48aa9e33542016b7a4052e001aaa536fca74813cb",
|
||||
low.GenerateHashString(&sch))
|
||||
|
||||
}
|
||||
|
||||
func TestSchemaProxy_Build_CheckRef(t *testing.T) {
|
||||
@@ -37,4 +47,6 @@ func TestSchemaProxy_Build_CheckRef(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, sch.IsSchemaReference())
|
||||
assert.Equal(t, "wat", sch.GetSchemaReference())
|
||||
assert.Equal(t, "f00a787f7492a95e165b470702f4fe9373583fbdc025b2c8bdf0262cc48fcff4",
|
||||
low.GenerateHashString(&sch))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package low
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/resolver"
|
||||
@@ -1488,3 +1489,26 @@ x-tacos: [1,2,3]`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type test_fresh struct {
|
||||
val string
|
||||
}
|
||||
|
||||
func (f test_fresh) Hash() [32]byte {
|
||||
return sha256.Sum256([]byte(f.val))
|
||||
}
|
||||
func TestAreEqual(t *testing.T) {
|
||||
assert.True(t, AreEqual(test_fresh{val: "hello"}, test_fresh{val: "hello"}))
|
||||
assert.False(t, AreEqual(test_fresh{val: "hello"}, test_fresh{val: "goodbye"}))
|
||||
assert.False(t, AreEqual(nil, nil))
|
||||
}
|
||||
|
||||
func TestGenerateHashString(t *testing.T) {
|
||||
|
||||
assert.Equal(t, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824",
|
||||
GenerateHashString(test_fresh{val: "hello"}))
|
||||
|
||||
assert.Equal(t, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824",
|
||||
GenerateHashString("hello"))
|
||||
|
||||
}
|
||||
|
||||
@@ -273,6 +273,51 @@ func TestSetField_ArrayHelper(t *testing.T) {
|
||||
assert.Len(t, ins.Thing.Value, 3)
|
||||
}
|
||||
|
||||
func TestSetField_Enum_Helper(t *testing.T) {
|
||||
|
||||
type internal struct {
|
||||
Thing NodeReference[[]ValueReference[any]]
|
||||
}
|
||||
|
||||
yml := `thing:
|
||||
- nice
|
||||
- rice
|
||||
- slice`
|
||||
|
||||
ins := new(internal)
|
||||
var rootNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(yml), &rootNode)
|
||||
assert.NoError(t, mErr)
|
||||
|
||||
try := BuildModel(rootNode.Content[0], ins)
|
||||
assert.NoError(t, try)
|
||||
assert.Len(t, ins.Thing.Value, 3)
|
||||
}
|
||||
|
||||
func TestSetField_Default_Helper(t *testing.T) {
|
||||
|
||||
type cake struct {
|
||||
thing int
|
||||
}
|
||||
|
||||
// this should be ignored, no custom objects in here my friend.
|
||||
type internal struct {
|
||||
Thing cake
|
||||
}
|
||||
|
||||
yml := `thing:
|
||||
type: cake`
|
||||
|
||||
ins := new(internal)
|
||||
var rootNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(yml), &rootNode)
|
||||
assert.NoError(t, mErr)
|
||||
|
||||
try := BuildModel(rootNode.Content[0], ins)
|
||||
assert.NoError(t, try)
|
||||
assert.Equal(t, 0, ins.Thing.thing)
|
||||
}
|
||||
|
||||
func TestSetField_Ignore(t *testing.T) {
|
||||
|
||||
type Complex struct {
|
||||
|
||||
@@ -87,6 +87,7 @@ func (n NodeReference[T]) IsEmpty() bool {
|
||||
}
|
||||
|
||||
func (n NodeReference[T]) IsReferenceNode() bool {
|
||||
if n.KeyNode != nil {
|
||||
for k := range n.KeyNode.Content {
|
||||
if k%2 == 0 {
|
||||
if n.KeyNode.Content[k].Value == "$ref" {
|
||||
@@ -94,6 +95,7 @@ func (n NodeReference[T]) IsReferenceNode() bool {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package low
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/resolver"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -31,11 +32,28 @@ func TestNodeReference_Mutate(t *testing.T) {
|
||||
Line: 22,
|
||||
Column: 23,
|
||||
}
|
||||
nr.KeyNode = &yaml.Node{
|
||||
Line: 22,
|
||||
Column: 23,
|
||||
}
|
||||
n := nr.Mutate("nice one!")
|
||||
assert.NotNil(t, nr.GetValueNode())
|
||||
assert.Empty(t, nr.GetValue())
|
||||
assert.False(t, nr.IsReferenceNode())
|
||||
assert.Equal(t, "nice one!", n.Value)
|
||||
assert.Equal(t, "nice one!", nr.ValueNode.Value)
|
||||
}
|
||||
|
||||
func TestNodeReference_RefNode(t *testing.T) {
|
||||
nr := new(NodeReference[string])
|
||||
nr.KeyNode = &yaml.Node{
|
||||
Content: []*yaml.Node{&yaml.Node{
|
||||
Value: "$ref",
|
||||
}},
|
||||
}
|
||||
assert.True(t, nr.IsReferenceNode())
|
||||
}
|
||||
|
||||
func TestValueReference_Mutate(t *testing.T) {
|
||||
nr := new(ValueReference[string])
|
||||
nr.ValueNode = &yaml.Node{
|
||||
@@ -59,6 +77,8 @@ func TestValueReference_GenerateMapKey(t *testing.T) {
|
||||
Column: 23,
|
||||
}
|
||||
assert.Equal(t, "22:23", nr.GenerateMapKey())
|
||||
assert.NotNil(t, nr.GetValueNode())
|
||||
assert.Empty(t, nr.GetValue())
|
||||
}
|
||||
|
||||
func TestKeyReference_IsEmpty(t *testing.T) {
|
||||
@@ -307,5 +327,10 @@ func TestGetCircularReferenceResult_NothingFound(t *testing.T) {
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
|
||||
assert.Nil(t, GetCircularReferenceResult(idxNode.Content[0], idx))
|
||||
}
|
||||
|
||||
func TestHashToString(t *testing.T) {
|
||||
assert.Equal(t, "5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5",
|
||||
HashToString(sha256.Sum256([]byte("12345"))))
|
||||
|
||||
}
|
||||
|
||||
@@ -49,6 +49,26 @@ func TestDefinitions_Parameters_Build_Error(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestDefinitions_Hash(t *testing.T) {
|
||||
|
||||
yml := `nice:
|
||||
description: rice`
|
||||
|
||||
var idxNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&idxNode)
|
||||
|
||||
var n Definitions
|
||||
err := low.BuildModel(&idxNode, &n)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_ = n.Build(idxNode.Content[0], idx)
|
||||
assert.Equal(t, "26d23786e6873e1a337f8e9be85f7de1490e4ff6cd303c3b15e593a25a6a149d",
|
||||
low.GenerateHashString(&n))
|
||||
|
||||
}
|
||||
|
||||
func TestDefinitions_Responses_Build_Error(t *testing.T) {
|
||||
|
||||
yml := `gonna:
|
||||
|
||||
@@ -166,14 +166,14 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
||||
// for every component, build in a new thread!
|
||||
bChan := make(chan componentBuildResult[T])
|
||||
eChan := make(chan error)
|
||||
var buildComponent = func(label *yaml.Node, value *yaml.Node, c chan componentBuildResult[T], ec chan<- error) {
|
||||
var buildComponent = func(parentLabel string, label *yaml.Node, value *yaml.Node, c chan componentBuildResult[T], ec chan<- error) {
|
||||
var n T = new(N)
|
||||
|
||||
// if this is a reference, extract it (although components with references is an antipattern)
|
||||
// If you're building components as references... pls... stop, this code should not need to be here.
|
||||
// TODO: check circular crazy on this. It may explode
|
||||
var err error
|
||||
if h, _, _ := utils.IsNodeRefValue(value); h && label.Value != SchemasLabel {
|
||||
if h, _, _ := utils.IsNodeRefValue(value); h && parentLabel != SchemasLabel {
|
||||
value, err = low.LocateRefNode(value, idx)
|
||||
}
|
||||
if err != nil {
|
||||
@@ -210,7 +210,7 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
||||
continue
|
||||
}
|
||||
totalComponents++
|
||||
go buildComponent(currentLabel, v, bChan, eChan)
|
||||
go buildComponent(label, currentLabel, v, bChan, eChan)
|
||||
}
|
||||
|
||||
completedComponents := 0
|
||||
|
||||
@@ -138,6 +138,28 @@ func TestComponents_Build_Fail(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestComponents_Build_ParameterFail(t *testing.T) {
|
||||
|
||||
yml := `components:
|
||||
parameters:
|
||||
pizza:
|
||||
schema:
|
||||
$ref: '#/this is a problem.'`
|
||||
|
||||
var idxNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndex(&idxNode)
|
||||
|
||||
var n Components
|
||||
err := low.BuildModel(&idxNode, &n)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = n.Build(idxNode.Content[0], idx)
|
||||
assert.Error(t, err)
|
||||
|
||||
}
|
||||
|
||||
func TestComponents_Build_Fail_TypeFail(t *testing.T) {
|
||||
|
||||
yml := `components:
|
||||
|
||||
@@ -53,6 +53,12 @@ info:
|
||||
servers:
|
||||
- url: https://quobix.com/api`
|
||||
|
||||
var OpenApi31 = `openapi: 3.1
|
||||
info:
|
||||
title: Test API, valid, but not quite valid
|
||||
servers:
|
||||
- url: https://quobix.com/api`
|
||||
|
||||
var OpenApiFalse = `openapi: false
|
||||
info:
|
||||
title: Test API version is a bool?
|
||||
@@ -161,6 +167,14 @@ func TestExtractSpecInfo_OpenAPIWat(t *testing.T) {
|
||||
assert.Equal(t, "3.2", r.Version)
|
||||
}
|
||||
|
||||
func TestExtractSpecInfo_OpenAPI31(t *testing.T) {
|
||||
|
||||
r, e := ExtractSpecInfo([]byte(OpenApi31))
|
||||
assert.Nil(t, e)
|
||||
assert.Equal(t, OpenApi3, r.SpecType)
|
||||
assert.Equal(t, "3.1", r.Version)
|
||||
}
|
||||
|
||||
func TestExtractSpecInfo_OpenAPIFalse(t *testing.T) {
|
||||
|
||||
spec, e := ExtractSpecInfo([]byte(OpenApiFalse))
|
||||
|
||||
@@ -714,6 +714,18 @@ responses:
|
||||
$ref: '#/definitions/ApiResponse'
|
||||
headers:
|
||||
someHeader:
|
||||
format: something
|
||||
pattern: a nice pattern
|
||||
exclusiveMinimum: false
|
||||
exclusiveMaximum: false
|
||||
minimum: 1
|
||||
maximum: 2
|
||||
maxItems: 3
|
||||
minItems: 1
|
||||
minLength: 1
|
||||
maxLength: 10
|
||||
multipleOf: 20
|
||||
uniqueItems: false
|
||||
type: array
|
||||
enum: [one, two]
|
||||
items:
|
||||
|
||||
@@ -274,22 +274,6 @@ func FindKeyNodeFullTop(key string, nodes []*yaml.Node) (keyNode *yaml.Node, lab
|
||||
return nodes[i], nodes[i], nodes[i+1] // next node is what we need.
|
||||
}
|
||||
}
|
||||
for q, v := range nodes {
|
||||
if q%2 != 0 {
|
||||
continue
|
||||
}
|
||||
if key == v.Value {
|
||||
if IsNodeMap(v) {
|
||||
if q+1 == len(v.Content) {
|
||||
return v, v.Content[q], v.Content[q]
|
||||
}
|
||||
return v, v.Content[q], v.Content[q+1]
|
||||
}
|
||||
if IsNodeArray(v) {
|
||||
return v, v.Content[q], v.Content[q]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -424,6 +424,34 @@ func TestFindKeyNode_NotFound(t *testing.T) {
|
||||
assert.Nil(t, v)
|
||||
}
|
||||
|
||||
func TestFindKeyFullNodeTop(t *testing.T) {
|
||||
a := &yaml.Node{
|
||||
Value: "fish",
|
||||
}
|
||||
b := &yaml.Node{
|
||||
Value: "paste",
|
||||
}
|
||||
|
||||
c, d, e := FindKeyNodeFullTop("fish", []*yaml.Node{a, b})
|
||||
assert.Equal(t, "fish", c.Value)
|
||||
assert.Equal(t, "fish", d.Value)
|
||||
assert.Equal(t, "paste", e.Value)
|
||||
}
|
||||
|
||||
func TestFindKeyFullNode_NotFound(t *testing.T) {
|
||||
a := &yaml.Node{
|
||||
Value: "fish",
|
||||
}
|
||||
b := &yaml.Node{
|
||||
Value: "paste",
|
||||
}
|
||||
|
||||
c, d, e := FindKeyNodeFullTop("lemons", []*yaml.Node{a, b})
|
||||
assert.Nil(t, c)
|
||||
assert.Nil(t, d)
|
||||
assert.Nil(t, e)
|
||||
}
|
||||
|
||||
func TestMakeTagReadable(t *testing.T) {
|
||||
n := &yaml.Node{
|
||||
Tag: "!!map",
|
||||
@@ -599,6 +627,8 @@ func TestDetectCase(t *testing.T) {
|
||||
assert.Equal(t, SnakeCase, DetectCase("snakes_on_a_plane"))
|
||||
assert.Equal(t, KebabCase, DetectCase("chicken-be-be-beef-or-pork"))
|
||||
assert.Equal(t, RegularCase, DetectCase("kebab-TimeIn_london-TOWN"))
|
||||
assert.Equal(t, UnknownCase, DetectCase(""))
|
||||
|
||||
}
|
||||
|
||||
func TestIsNodeRefValue(t *testing.T) {
|
||||
|
||||
@@ -175,9 +175,10 @@ func CheckForModification[T any](l, r *yaml.Node, label string, changes *[]*Chan
|
||||
CreateChange(changes, Modified, label, l, r, breaking, orig, new)
|
||||
}
|
||||
// the values may have not changed, but the tag (node type) type may have
|
||||
if l != nil && l.Value != "" && r != nil && r.Value != "" && r.Value != l.Value && r.Tag != l.Tag {
|
||||
CreateChange(changes, Modified, label, l, r, breaking, orig, new)
|
||||
}
|
||||
// todo: this is currently untestable, no a single test triggers it (yet)
|
||||
//if l != nil && l.Value != "" && r != nil && r.Value != "" && r.Value != l.Value && r.Tag != l.Tag {
|
||||
// CreateChange(changes, Modified, label, l, r, breaking, orig, new)
|
||||
//}
|
||||
}
|
||||
|
||||
// CheckMapForChanges checks a left and right low level map for any additions, subtractions or modifications to
|
||||
@@ -227,6 +228,7 @@ func CheckMapForChanges[T any, R any](expLeft, expRight map[low.KeyReference[str
|
||||
chLock.Lock()
|
||||
expChanges[k] = compareFunc(p[k].Value, h[k].Value)
|
||||
chLock.Unlock()
|
||||
|
||||
doneChan <- true
|
||||
}
|
||||
|
||||
@@ -256,75 +258,6 @@ func CheckMapForChanges[T any, R any](expLeft, expRight map[low.KeyReference[str
|
||||
return expChanges
|
||||
}
|
||||
|
||||
//// CheckMapForChangesUntyped checks a left and right low level map for any additions, subtractions or modifications to
|
||||
//// values. The compareFunc can be generic and accept any type
|
||||
//func CheckMapForChangesUntyped[T any, R any](expLeft, expRight map[low.KeyReference[string]]low.ValueReference[T],
|
||||
// changes *[]*Change, label string, compareFunc func(l, r any) R) map[string]R {
|
||||
//
|
||||
// lHashes := make(map[string]string)
|
||||
// rHashes := make(map[string]string)
|
||||
// lValues := make(map[string]low.ValueReference[T])
|
||||
// rValues := make(map[string]low.ValueReference[T])
|
||||
//
|
||||
// for k := range expLeft {
|
||||
// lHashes[k.Value] = low.GenerateHashString(expLeft[k].Value)
|
||||
// lValues[k.Value] = expLeft[k]
|
||||
// }
|
||||
//
|
||||
// for k := range expRight {
|
||||
// rHashes[k.Value] = low.GenerateHashString(expRight[k].Value)
|
||||
// rValues[k.Value] = expRight[k]
|
||||
// }
|
||||
//
|
||||
// expChanges := make(map[string]R)
|
||||
//
|
||||
// checkLeft := func(k string, doneChan chan bool, f, g map[string]string, p, h map[string]low.ValueReference[T]) {
|
||||
// rhash := g[k]
|
||||
// if rhash == "" {
|
||||
// if p[k].GetValueNode().Value == "" {
|
||||
// p[k].GetValueNode().Value = k // yes, a dirty thing, but it's clean for the consumer.
|
||||
// }
|
||||
// CreateChange(changes, ObjectRemoved, label,
|
||||
// p[k].GetValueNode(), nil, true,
|
||||
// p[k].GetValue(), nil)
|
||||
// doneChan <- true
|
||||
// return
|
||||
// }
|
||||
// if f[k] == g[k] {
|
||||
// doneChan <- true
|
||||
// return
|
||||
// }
|
||||
// // run comparison.
|
||||
// expChanges[k] = compareFunc(p[k].Value, h[k].Value)
|
||||
// doneChan <- true
|
||||
// }
|
||||
//
|
||||
// doneChan := make(chan bool)
|
||||
// count := 0
|
||||
//
|
||||
// // check left example hashes
|
||||
// for k := range lHashes {
|
||||
// count++
|
||||
// go checkLeft(k, doneChan, lHashes, rHashes, lValues, rValues)
|
||||
// }
|
||||
//
|
||||
// //check right example hashes
|
||||
// for k := range rHashes {
|
||||
// count++
|
||||
// go checkRightValue(k, doneChan, lHashes, rValues, changes, label)
|
||||
// }
|
||||
//
|
||||
// // wait for all done signals.
|
||||
// completed := 0
|
||||
// for completed < count {
|
||||
// select {
|
||||
// case <-doneChan:
|
||||
// completed++
|
||||
// }
|
||||
// }
|
||||
// return expChanges
|
||||
//}
|
||||
|
||||
func checkRightValue[T any](k string, doneChan chan bool, f map[string]string, p map[string]low.ValueReference[T],
|
||||
changes *[]*Change, label string, lock *sync.Mutex) {
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/resolver"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"testing"
|
||||
@@ -770,6 +771,50 @@ func TestCompareComponents_OpenAPI_Responses_FullBuild_IdenticalRef(t *testing.T
|
||||
assert.Nil(t, extChanges)
|
||||
}
|
||||
|
||||
func TestCompareComponents_OpenAPI_Responses_FullBuild_CircularRef(t *testing.T) {
|
||||
left := `components:
|
||||
responses:
|
||||
coffee:
|
||||
$ref: '#/components/responses/tv'
|
||||
tv:
|
||||
$ref: '#/components/responses/coffee'`
|
||||
|
||||
right := `components:
|
||||
responses:
|
||||
coffee:
|
||||
$ref: '#/components/responses/tv'
|
||||
tv:
|
||||
$ref: '#/components/responses/coffee'`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.Components
|
||||
var rDoc v3.Components
|
||||
|
||||
_ = low.BuildModel(lNode.Content[0], &lDoc)
|
||||
_ = low.BuildModel(rNode.Content[0], &rDoc)
|
||||
|
||||
idx := index.NewSpecIndex(&lNode)
|
||||
idx2 := index.NewSpecIndex(&rNode)
|
||||
|
||||
// resolver required to check circular refs.
|
||||
re1 := resolver.NewResolver(idx)
|
||||
re2 := resolver.NewResolver(idx2)
|
||||
|
||||
re1.CheckForCircularReferences()
|
||||
re2.CheckForCircularReferences()
|
||||
|
||||
_ = lDoc.Build(lNode.Content[0], idx)
|
||||
_ = rDoc.Build(rNode.Content[0], idx2)
|
||||
|
||||
// compare.
|
||||
extChanges := CompareComponents(&lDoc, &rDoc)
|
||||
assert.Nil(t, extChanges)
|
||||
}
|
||||
|
||||
func TestCompareComponents_OpenAPI_Responses_Modify(t *testing.T) {
|
||||
|
||||
left := `responses:
|
||||
@@ -1205,6 +1250,38 @@ func TestCompareComponents_OpenAPI_SecuritySchemes_Equal(t *testing.T) {
|
||||
assert.Nil(t, extChanges)
|
||||
}
|
||||
|
||||
func TestCompareComponents_OpenAPI_SecuritySchemes_Modified(t *testing.T) {
|
||||
|
||||
left := `securitySchemes:
|
||||
scheme1:
|
||||
description: a scheme
|
||||
scheme2:
|
||||
description: another scheme`
|
||||
|
||||
right := `securitySchemes:
|
||||
scheme1:
|
||||
description: a scheme that changed
|
||||
scheme2:
|
||||
description: another scheme that also changed`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.Components
|
||||
var rDoc v3.Components
|
||||
_ = low.BuildModel(lNode.Content[0], &lDoc)
|
||||
_ = low.BuildModel(rNode.Content[0], &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare.
|
||||
extChanges := CompareComponents(&lDoc, &rDoc)
|
||||
assert.Equal(t, 2, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
}
|
||||
|
||||
func TestCompareComponents_OpenAPI_Links_Equal(t *testing.T) {
|
||||
|
||||
left := `links:
|
||||
|
||||
@@ -225,7 +225,7 @@ func TestCompareSchemas_RefChanged(t *testing.T) {
|
||||
assert.NotNil(t, changes)
|
||||
assert.Len(t, changes.Changes, 1)
|
||||
assert.Equal(t, Modified, changes.Changes[0].ChangeType)
|
||||
assert.Equal(t, "string", changes.Changes[0].New)
|
||||
assert.Equal(t, "#/components/schemas/Yo", changes.Changes[0].New)
|
||||
}
|
||||
|
||||
func TestCompareSchemas_RefToInline(t *testing.T) {
|
||||
@@ -253,8 +253,8 @@ func TestCompareSchemas_RefToInline(t *testing.T) {
|
||||
assert.NotNil(t, changes)
|
||||
assert.Len(t, changes.Changes, 1)
|
||||
assert.Equal(t, Modified, changes.Changes[0].ChangeType)
|
||||
assert.Equal(t, v3.TypeLabel, changes.Changes[0].Property)
|
||||
assert.Equal(t, "int", changes.Changes[0].Original)
|
||||
assert.Equal(t, v3.RefLabel, changes.Changes[0].Property)
|
||||
assert.Equal(t, "#/components/schemas/Yo", changes.Changes[0].Original)
|
||||
|
||||
}
|
||||
|
||||
@@ -283,8 +283,8 @@ func TestCompareSchemas_InlineToRef(t *testing.T) {
|
||||
assert.NotNil(t, changes)
|
||||
assert.Len(t, changes.Changes, 1)
|
||||
assert.Equal(t, Modified, changes.Changes[0].ChangeType)
|
||||
assert.Equal(t, v3.TypeLabel, changes.Changes[0].Property)
|
||||
assert.Equal(t, "int", changes.Changes[0].New)
|
||||
assert.Equal(t, v3.RefLabel, changes.Changes[0].Property)
|
||||
assert.Equal(t, "#/components/schemas/Yo", changes.Changes[0].New)
|
||||
|
||||
}
|
||||
|
||||
@@ -313,6 +313,31 @@ func TestCompareSchemas_Identical(t *testing.T) {
|
||||
assert.Nil(t, changes)
|
||||
}
|
||||
|
||||
func TestCompareSchemas_Identical_Ref(t *testing.T) {
|
||||
left := `components:
|
||||
schemas:
|
||||
Yo:
|
||||
type: int
|
||||
OK:
|
||||
$ref: '#/components/schemas/Yo'`
|
||||
|
||||
right := `components:
|
||||
schemas:
|
||||
Yo:
|
||||
type: int
|
||||
OK:
|
||||
$ref: '#/components/schemas/Yo'`
|
||||
|
||||
leftDoc, rightDoc := test_BuildDoc(left, right)
|
||||
|
||||
// extract left reference schema and non reference schema.
|
||||
lSchemaProxy := leftDoc.Components.Value.FindSchema("OK").Value
|
||||
rSchemaProxy := rightDoc.Components.Value.FindSchema("OK").Value
|
||||
|
||||
changes := CompareSchemas(rSchemaProxy, lSchemaProxy)
|
||||
assert.Nil(t, changes)
|
||||
}
|
||||
|
||||
func TestCompareSchemas_RequiredAdded(t *testing.T) {
|
||||
left := `components:
|
||||
schemas:
|
||||
|
||||
Reference in New Issue
Block a user