mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-09 20:47:44 +00:00
fix: handle example comparison correctly. #61
examples can be anything, most commonly maps. previously `libopenapi` did not check maps correctly. Now it does. It was also creating a panic by inserting a nil pointer as the value to a map key. This has also been fixed. Examples are the only element that use this pattern for comparison.
This commit is contained in:
@@ -113,14 +113,6 @@ func NewPropertyChanges(changes []*Change) *PropertyChanges {
|
|||||||
return &PropertyChanges{Changes: changes}
|
return &PropertyChanges{Changes: changes}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SortByChangeType will order changes by the types of change they represent,
|
|
||||||
// This is a destructive action and will permanently re-order Changes.
|
|
||||||
//func (p PropertyChanges[T]) SortByChangeType() {
|
|
||||||
// sort.SliceStable(p.Changes, func(i, j int) bool {
|
|
||||||
// return p.Changes[i].ChangeType < p.Changes[j].ChangeType
|
|
||||||
// })
|
|
||||||
//}
|
|
||||||
|
|
||||||
// PropertyCheck is used by functions to check the state of left and right values.
|
// PropertyCheck is used by functions to check the state of left and right values.
|
||||||
type PropertyCheck struct {
|
type PropertyCheck struct {
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -250,7 +251,12 @@ func CheckMapForChangesWithComp[T any, R any](expLeft, expRight map[low.KeyRefer
|
|||||||
// run comparison.
|
// run comparison.
|
||||||
if compare {
|
if compare {
|
||||||
chLock.Lock()
|
chLock.Lock()
|
||||||
expChanges[k] = compareFunc(p[k].Value, h[k].Value)
|
ch := compareFunc(p[k].Value, h[k].Value)
|
||||||
|
// incorrect map results were being generated causing panics.
|
||||||
|
// https://github.com/pb33f/libopenapi/issues/61
|
||||||
|
if !reflect.ValueOf(&ch).Elem().IsZero() {
|
||||||
|
expChanges[k] = ch
|
||||||
|
}
|
||||||
chLock.Unlock()
|
chLock.Unlock()
|
||||||
}
|
}
|
||||||
doneChan <- true
|
doneChan <- true
|
||||||
|
|||||||
@@ -1074,3 +1074,86 @@ webhooks:
|
|||||||
assert.Equal(t, 2, extChanges.TotalChanges())
|
assert.Equal(t, 2, extChanges.TotalChanges())
|
||||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCompareDocuments_OpenAPIExampleMapChanges(t *testing.T) {
|
||||||
|
left := `openapi: 3.0.0
|
||||||
|
paths:
|
||||||
|
/:
|
||||||
|
post:
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
examples:
|
||||||
|
test:
|
||||||
|
value:
|
||||||
|
map:
|
||||||
|
deep:
|
||||||
|
date: 2020-01-01`
|
||||||
|
|
||||||
|
right := `openapi: 3.0.0
|
||||||
|
paths:
|
||||||
|
/:
|
||||||
|
post:
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
examples:
|
||||||
|
test:
|
||||||
|
value:
|
||||||
|
map:
|
||||||
|
deep:
|
||||||
|
date: "2020-01-04"`
|
||||||
|
|
||||||
|
// have to build docs fully to get access to objects
|
||||||
|
siLeft, _ := datamodel.ExtractSpecInfo([]byte(left))
|
||||||
|
siRight, _ := datamodel.ExtractSpecInfo([]byte(right))
|
||||||
|
|
||||||
|
lDoc, _ := v3.CreateDocument(siLeft)
|
||||||
|
rDoc, _ := v3.CreateDocument(siRight)
|
||||||
|
|
||||||
|
// compare.
|
||||||
|
extChanges := CompareDocuments(lDoc, rDoc)
|
||||||
|
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||||
|
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareDocuments_OpenAPIExampleNoExampleMapChanges(t *testing.T) {
|
||||||
|
left := `openapi: 3.0.0
|
||||||
|
paths:
|
||||||
|
/:
|
||||||
|
post:
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
examples:
|
||||||
|
test:
|
||||||
|
value:
|
||||||
|
map:
|
||||||
|
deep:
|
||||||
|
date: 2020-01-01`
|
||||||
|
|
||||||
|
right := `openapi: 3.0.0
|
||||||
|
paths:
|
||||||
|
/:
|
||||||
|
post:
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
examples:
|
||||||
|
test:
|
||||||
|
value:
|
||||||
|
map:
|
||||||
|
deep:
|
||||||
|
date: 2020-01-01`
|
||||||
|
|
||||||
|
// have to build docs fully to get access to objects
|
||||||
|
siLeft, _ := datamodel.ExtractSpecInfo([]byte(left))
|
||||||
|
siRight, _ := datamodel.ExtractSpecInfo([]byte(right))
|
||||||
|
|
||||||
|
lDoc, _ := v3.CreateDocument(siLeft)
|
||||||
|
rDoc, _ := v3.CreateDocument(siRight)
|
||||||
|
|
||||||
|
// compare.
|
||||||
|
extChanges := CompareDocuments(lDoc, rDoc)
|
||||||
|
assert.Nil(t, extChanges)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
@@ -72,7 +73,17 @@ func CompareExamples(l, r *base.Example) *ExampleChanges {
|
|||||||
z := 0
|
z := 0
|
||||||
for k := range l.Value.ValueNode.Content {
|
for k := range l.Value.ValueNode.Content {
|
||||||
if k%2 == 0 {
|
if k%2 == 0 {
|
||||||
lKeys[z] = fmt.Sprintf("%v-%v-%v", l.Value.ValueNode.Content[k].Value, l.Value.ValueNode.Content[k+1].Tag, l.Value.ValueNode.Content[k+1].Value)
|
// if there is no value (value is another map or something else), render the node into yaml and hash it.
|
||||||
|
// https://github.com/pb33f/libopenapi/issues/61
|
||||||
|
val := l.Value.ValueNode.Content[k+1].Value
|
||||||
|
if val == "" {
|
||||||
|
yaml, _ := yaml.Marshal(l.Value.ValueNode.Content[k+1].Content)
|
||||||
|
val = fmt.Sprint(sha256.Sum256(yaml))
|
||||||
|
}
|
||||||
|
lKeys[z] = fmt.Sprintf("%v-%v-%v",
|
||||||
|
l.Value.ValueNode.Content[k].Value,
|
||||||
|
l.Value.ValueNode.Content[k+1].Tag,
|
||||||
|
fmt.Sprintf("%x", val))
|
||||||
z++
|
z++
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
@@ -81,7 +92,17 @@ func CompareExamples(l, r *base.Example) *ExampleChanges {
|
|||||||
z = 0
|
z = 0
|
||||||
for k := range r.Value.ValueNode.Content {
|
for k := range r.Value.ValueNode.Content {
|
||||||
if k%2 == 0 {
|
if k%2 == 0 {
|
||||||
rKeys[z] = fmt.Sprintf("%v-%v-%v", r.Value.ValueNode.Content[k].Value, r.Value.ValueNode.Content[k+1].Tag, r.Value.ValueNode.Content[k+1].Value)
|
// if there is no value (value is another map or something else), render the node into yaml and hash it.
|
||||||
|
// https://github.com/pb33f/libopenapi/issues/61
|
||||||
|
val := r.Value.ValueNode.Content[k+1].Value
|
||||||
|
if val == "" {
|
||||||
|
yaml, _ := yaml.Marshal(r.Value.ValueNode.Content[k+1].Content)
|
||||||
|
val = fmt.Sprint(sha256.Sum256(yaml))
|
||||||
|
}
|
||||||
|
rKeys[z] = fmt.Sprintf("%v-%v-%v",
|
||||||
|
r.Value.ValueNode.Content[k].Value,
|
||||||
|
r.Value.ValueNode.Content[k+1].Tag,
|
||||||
|
fmt.Sprintf("%x", val))
|
||||||
z++
|
z++
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
|
|||||||
Reference in New Issue
Block a user