Mutation method updated to return new copy

with value node (pointer) and value (non pointer) returned.
This commit is contained in:
Dave Shanley
2022-09-13 09:32:08 -04:00
parent a2b7119af7
commit aa4422fa74
4 changed files with 167 additions and 177 deletions

View File

@@ -40,8 +40,10 @@ func (n NodeReference[T]) GenerateMapKey() string {
return fmt.Sprintf("%d:%d", n.ValueNode.Line, n.ValueNode.Column) return fmt.Sprintf("%d:%d", n.ValueNode.Line, n.ValueNode.Column)
} }
func (n NodeReference[T]) Mutate(value T) { func (n NodeReference[T]) Mutate(value T) NodeReference[T] {
n.ValueNode.Value = fmt.Sprintf("%v", value) n.ValueNode.Value = fmt.Sprintf("%v", value)
n.Value = value
return n
} }
func (n ValueReference[T]) IsEmpty() bool { func (n ValueReference[T]) IsEmpty() bool {
@@ -60,8 +62,10 @@ func (n KeyReference[T]) GenerateMapKey() string {
return fmt.Sprintf("%d:%d", n.KeyNode.Line, n.KeyNode.Column) return fmt.Sprintf("%d:%d", n.KeyNode.Line, n.KeyNode.Column)
} }
func (n ValueReference[T]) Mutate(value T) { func (n ValueReference[T]) Mutate(value T) ValueReference[T] {
n.ValueNode.Value = fmt.Sprintf("%v", value) n.ValueNode.Value = fmt.Sprintf("%v", value)
n.Value = value
return n
} }
func IsCircular(node *yaml.Node, idx *index.SpecIndex) bool { func IsCircular(node *yaml.Node, idx *index.SpecIndex) bool {

View File

@@ -4,58 +4,80 @@
package low package low
import ( import (
"github.com/pb33f/libopenapi/index" "github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/resolver" "github.com/pb33f/libopenapi/resolver"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"testing" "testing"
) )
func TestNodeReference_IsEmpty(t *testing.T) { func TestNodeReference_IsEmpty(t *testing.T) {
nr := new(NodeReference[string]) nr := new(NodeReference[string])
assert.True(t, nr.IsEmpty()) assert.True(t, nr.IsEmpty())
} }
func TestNodeReference_GenerateMapKey(t *testing.T) { func TestNodeReference_GenerateMapKey(t *testing.T) {
nr := new(NodeReference[string]) nr := new(NodeReference[string])
nr.ValueNode = &yaml.Node{ nr.ValueNode = &yaml.Node{
Line: 22, Line: 22,
Column: 23, Column: 23,
} }
assert.Equal(t, "22:23", nr.GenerateMapKey()) assert.Equal(t, "22:23", nr.GenerateMapKey())
}
func TestNodeReference_Mutate(t *testing.T) {
nr := new(NodeReference[string])
nr.ValueNode = &yaml.Node{
Line: 22,
Column: 23,
}
n := nr.Mutate("nice one!")
assert.Equal(t, "nice one!", n.Value)
assert.Equal(t, "nice one!", nr.ValueNode.Value)
}
func TestValueReference_Mutate(t *testing.T) {
nr := new(ValueReference[string])
nr.ValueNode = &yaml.Node{
Line: 22,
Column: 23,
}
n := nr.Mutate("nice one!")
assert.Equal(t, "nice one!", n.Value)
assert.Equal(t, "nice one!", nr.ValueNode.Value)
} }
func TestValueReference_IsEmpty(t *testing.T) { func TestValueReference_IsEmpty(t *testing.T) {
nr := new(ValueReference[string]) nr := new(ValueReference[string])
assert.True(t, nr.IsEmpty()) assert.True(t, nr.IsEmpty())
} }
func TestValueReference_GenerateMapKey(t *testing.T) { func TestValueReference_GenerateMapKey(t *testing.T) {
nr := new(ValueReference[string]) nr := new(ValueReference[string])
nr.ValueNode = &yaml.Node{ nr.ValueNode = &yaml.Node{
Line: 22, Line: 22,
Column: 23, Column: 23,
} }
assert.Equal(t, "22:23", nr.GenerateMapKey()) assert.Equal(t, "22:23", nr.GenerateMapKey())
} }
func TestKeyReference_IsEmpty(t *testing.T) { func TestKeyReference_IsEmpty(t *testing.T) {
nr := new(KeyReference[string]) nr := new(KeyReference[string])
assert.True(t, nr.IsEmpty()) assert.True(t, nr.IsEmpty())
} }
func TestKeyReference_GenerateMapKey(t *testing.T) { func TestKeyReference_GenerateMapKey(t *testing.T) {
nr := new(KeyReference[string]) nr := new(KeyReference[string])
nr.KeyNode = &yaml.Node{ nr.KeyNode = &yaml.Node{
Line: 22, Line: 22,
Column: 23, Column: 23,
} }
assert.Equal(t, "22:23", nr.GenerateMapKey()) assert.Equal(t, "22:23", nr.GenerateMapKey())
} }
func TestIsCircular_LookupFromJourney(t *testing.T) { func TestIsCircular_LookupFromJourney(t *testing.T) {
yml := `components: yml := `components:
schemas: schemas:
Something: Something:
properties: properties:
@@ -66,28 +88,28 @@ func TestIsCircular_LookupFromJourney(t *testing.T) {
something: something:
$ref: '#/components/schemas/Something'` $ref: '#/components/schemas/Something'`
var iNode yaml.Node var iNode yaml.Node
mErr := yaml.Unmarshal([]byte(yml), &iNode) mErr := yaml.Unmarshal([]byte(yml), &iNode)
assert.NoError(t, mErr) assert.NoError(t, mErr)
idx := index.NewSpecIndex(&iNode) idx := index.NewSpecIndex(&iNode)
yml = `$ref: '#/components/schemas/Something'` yml = `$ref: '#/components/schemas/Something'`
resolve := resolver.NewResolver(idx) resolve := resolver.NewResolver(idx)
errs := resolve.CheckForCircularReferences() errs := resolve.CheckForCircularReferences()
assert.Len(t, errs, 1) assert.Len(t, errs, 1)
var idxNode yaml.Node var idxNode yaml.Node
_ = yaml.Unmarshal([]byte(yml), &idxNode) _ = yaml.Unmarshal([]byte(yml), &idxNode)
ref, err := LocateRefNode(idxNode.Content[0], idx) ref, err := LocateRefNode(idxNode.Content[0], idx)
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, IsCircular(ref, idx)) assert.True(t, IsCircular(ref, idx))
} }
func TestIsCircular_LookupFromLoopPoint(t *testing.T) { func TestIsCircular_LookupFromLoopPoint(t *testing.T) {
yml := `components: yml := `components:
schemas: schemas:
Something: Something:
properties: properties:
@@ -98,28 +120,28 @@ func TestIsCircular_LookupFromLoopPoint(t *testing.T) {
something: something:
$ref: '#/components/schemas/Something'` $ref: '#/components/schemas/Something'`
var iNode yaml.Node var iNode yaml.Node
mErr := yaml.Unmarshal([]byte(yml), &iNode) mErr := yaml.Unmarshal([]byte(yml), &iNode)
assert.NoError(t, mErr) assert.NoError(t, mErr)
idx := index.NewSpecIndex(&iNode) idx := index.NewSpecIndex(&iNode)
yml = `$ref: '#/components/schemas/Nothing'` yml = `$ref: '#/components/schemas/Nothing'`
resolve := resolver.NewResolver(idx) resolve := resolver.NewResolver(idx)
errs := resolve.CheckForCircularReferences() errs := resolve.CheckForCircularReferences()
assert.Len(t, errs, 1) assert.Len(t, errs, 1)
var idxNode yaml.Node var idxNode yaml.Node
_ = yaml.Unmarshal([]byte(yml), &idxNode) _ = yaml.Unmarshal([]byte(yml), &idxNode)
ref, err := LocateRefNode(idxNode.Content[0], idx) ref, err := LocateRefNode(idxNode.Content[0], idx)
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, IsCircular(ref, idx)) assert.True(t, IsCircular(ref, idx))
} }
func TestIsCircular_FromRefLookup(t *testing.T) { func TestIsCircular_FromRefLookup(t *testing.T) {
yml := `components: yml := `components:
schemas: schemas:
NotCircle: NotCircle:
description: not a circle description: not a circle
@@ -132,38 +154,38 @@ func TestIsCircular_FromRefLookup(t *testing.T) {
something: something:
$ref: '#/components/schemas/Something'` $ref: '#/components/schemas/Something'`
var iNode yaml.Node var iNode yaml.Node
mErr := yaml.Unmarshal([]byte(yml), &iNode) mErr := yaml.Unmarshal([]byte(yml), &iNode)
assert.NoError(t, mErr) assert.NoError(t, mErr)
idx := index.NewSpecIndex(&iNode) idx := index.NewSpecIndex(&iNode)
resolve := resolver.NewResolver(idx) resolve := resolver.NewResolver(idx)
errs := resolve.CheckForCircularReferences() errs := resolve.CheckForCircularReferences()
assert.Len(t, errs, 1) assert.Len(t, errs, 1)
yml = `$ref: '#/components/schemas/Nothing'` yml = `$ref: '#/components/schemas/Nothing'`
var idxNode yaml.Node var idxNode yaml.Node
_ = yaml.Unmarshal([]byte(yml), &idxNode) _ = yaml.Unmarshal([]byte(yml), &idxNode)
assert.True(t, IsCircular(idxNode.Content[0], idx)) assert.True(t, IsCircular(idxNode.Content[0], idx))
yml = `$ref: '#/components/schemas/NotCircle'` yml = `$ref: '#/components/schemas/NotCircle'`
_ = yaml.Unmarshal([]byte(yml), &idxNode) _ = yaml.Unmarshal([]byte(yml), &idxNode)
assert.False(t, IsCircular(idxNode.Content[0], idx)) assert.False(t, IsCircular(idxNode.Content[0], idx))
} }
func TestIsCircular_NoNode(t *testing.T) { func TestIsCircular_NoNode(t *testing.T) {
assert.False(t, IsCircular(nil, nil)) assert.False(t, IsCircular(nil, nil))
} }
func TestGetCircularReferenceResult_NoNode(t *testing.T) { func TestGetCircularReferenceResult_NoNode(t *testing.T) {
assert.Nil(t, GetCircularReferenceResult(nil, nil)) assert.Nil(t, GetCircularReferenceResult(nil, nil))
} }
func TestGetCircularReferenceResult_FromJourney(t *testing.T) { func TestGetCircularReferenceResult_FromJourney(t *testing.T) {
yml := `components: yml := `components:
schemas: schemas:
Something: Something:
properties: properties:
@@ -174,31 +196,31 @@ func TestGetCircularReferenceResult_FromJourney(t *testing.T) {
something: something:
$ref: '#/components/schemas/Something'` $ref: '#/components/schemas/Something'`
var iNode yaml.Node var iNode yaml.Node
mErr := yaml.Unmarshal([]byte(yml), &iNode) mErr := yaml.Unmarshal([]byte(yml), &iNode)
assert.NoError(t, mErr) assert.NoError(t, mErr)
idx := index.NewSpecIndex(&iNode) idx := index.NewSpecIndex(&iNode)
yml = `$ref: '#/components/schemas/Something'` yml = `$ref: '#/components/schemas/Something'`
resolve := resolver.NewResolver(idx) resolve := resolver.NewResolver(idx)
errs := resolve.CheckForCircularReferences() errs := resolve.CheckForCircularReferences()
assert.Len(t, errs, 1) assert.Len(t, errs, 1)
var idxNode yaml.Node var idxNode yaml.Node
_ = yaml.Unmarshal([]byte(yml), &idxNode) _ = yaml.Unmarshal([]byte(yml), &idxNode)
ref, err := LocateRefNode(idxNode.Content[0], idx) ref, err := LocateRefNode(idxNode.Content[0], idx)
assert.NoError(t, err) assert.NoError(t, err)
circ := GetCircularReferenceResult(ref, idx) circ := GetCircularReferenceResult(ref, idx)
assert.NotNil(t, circ) assert.NotNil(t, circ)
assert.Equal(t, "Nothing -> Something -> Nothing", circ.GenerateJourneyPath()) assert.Equal(t, "Nothing -> Something -> Nothing", circ.GenerateJourneyPath())
} }
func TestGetCircularReferenceResult_FromLoopPoint(t *testing.T) { func TestGetCircularReferenceResult_FromLoopPoint(t *testing.T) {
yml := `components: yml := `components:
schemas: schemas:
Something: Something:
properties: properties:
@@ -209,31 +231,31 @@ func TestGetCircularReferenceResult_FromLoopPoint(t *testing.T) {
something: something:
$ref: '#/components/schemas/Something'` $ref: '#/components/schemas/Something'`
var iNode yaml.Node var iNode yaml.Node
mErr := yaml.Unmarshal([]byte(yml), &iNode) mErr := yaml.Unmarshal([]byte(yml), &iNode)
assert.NoError(t, mErr) assert.NoError(t, mErr)
idx := index.NewSpecIndex(&iNode) idx := index.NewSpecIndex(&iNode)
yml = `$ref: '#/components/schemas/Nothing'` yml = `$ref: '#/components/schemas/Nothing'`
resolve := resolver.NewResolver(idx) resolve := resolver.NewResolver(idx)
errs := resolve.CheckForCircularReferences() errs := resolve.CheckForCircularReferences()
assert.Len(t, errs, 1) assert.Len(t, errs, 1)
var idxNode yaml.Node var idxNode yaml.Node
_ = yaml.Unmarshal([]byte(yml), &idxNode) _ = yaml.Unmarshal([]byte(yml), &idxNode)
ref, err := LocateRefNode(idxNode.Content[0], idx) ref, err := LocateRefNode(idxNode.Content[0], idx)
assert.NoError(t, err) assert.NoError(t, err)
circ := GetCircularReferenceResult(ref, idx) circ := GetCircularReferenceResult(ref, idx)
assert.NotNil(t, circ) assert.NotNil(t, circ)
assert.Equal(t, "Nothing -> Something -> Nothing", circ.GenerateJourneyPath()) assert.Equal(t, "Nothing -> Something -> Nothing", circ.GenerateJourneyPath())
} }
func TestGetCircularReferenceResult_FromMappedRef(t *testing.T) { func TestGetCircularReferenceResult_FromMappedRef(t *testing.T) {
yml := `components: yml := `components:
schemas: schemas:
Something: Something:
properties: properties:
@@ -244,46 +266,46 @@ func TestGetCircularReferenceResult_FromMappedRef(t *testing.T) {
something: something:
$ref: '#/components/schemas/Something'` $ref: '#/components/schemas/Something'`
var iNode yaml.Node var iNode yaml.Node
mErr := yaml.Unmarshal([]byte(yml), &iNode) mErr := yaml.Unmarshal([]byte(yml), &iNode)
assert.NoError(t, mErr) assert.NoError(t, mErr)
idx := index.NewSpecIndex(&iNode) idx := index.NewSpecIndex(&iNode)
yml = `$ref: '#/components/schemas/Nothing'` yml = `$ref: '#/components/schemas/Nothing'`
resolve := resolver.NewResolver(idx) resolve := resolver.NewResolver(idx)
errs := resolve.CheckForCircularReferences() errs := resolve.CheckForCircularReferences()
assert.Len(t, errs, 1) assert.Len(t, errs, 1)
var idxNode yaml.Node var idxNode yaml.Node
_ = yaml.Unmarshal([]byte(yml), &idxNode) _ = yaml.Unmarshal([]byte(yml), &idxNode)
circ := GetCircularReferenceResult(idxNode.Content[0], idx) circ := GetCircularReferenceResult(idxNode.Content[0], idx)
assert.NotNil(t, circ) assert.NotNil(t, circ)
assert.Equal(t, "Nothing -> Something -> Nothing", circ.GenerateJourneyPath()) assert.Equal(t, "Nothing -> Something -> Nothing", circ.GenerateJourneyPath())
} }
func TestGetCircularReferenceResult_NothingFound(t *testing.T) { func TestGetCircularReferenceResult_NothingFound(t *testing.T) {
yml := `components: yml := `components:
schemas: schemas:
NotCircle: NotCircle:
description: not a circle` description: not a circle`
var iNode yaml.Node var iNode yaml.Node
mErr := yaml.Unmarshal([]byte(yml), &iNode) mErr := yaml.Unmarshal([]byte(yml), &iNode)
assert.NoError(t, mErr) assert.NoError(t, mErr)
idx := index.NewSpecIndex(&iNode) idx := index.NewSpecIndex(&iNode)
resolve := resolver.NewResolver(idx) resolve := resolver.NewResolver(idx)
errs := resolve.CheckForCircularReferences() errs := resolve.CheckForCircularReferences()
assert.Len(t, errs, 0) assert.Len(t, errs, 0)
var idxNode yaml.Node var idxNode yaml.Node
yml = `$ref: '#/components/schemas/NotCircle'` yml = `$ref: '#/components/schemas/NotCircle'`
_ = yaml.Unmarshal([]byte(yml), &idxNode) _ = yaml.Unmarshal([]byte(yml), &idxNode)
assert.Nil(t, GetCircularReferenceResult(idxNode.Content[0], idx)) assert.Nil(t, GetCircularReferenceResult(idxNode.Content[0], idx))
} }

View File

@@ -160,7 +160,12 @@ func TestDocument_Serialize_JSON_Modified(t *testing.T) {
v3Doc, _ := doc.BuildV3Document() v3Doc, _ := doc.BuildV3Document()
v3Doc.Model.Info.GoLow().Title.Mutate("The magic API - but now, altered!") // eventually this will be encapsulated up high.
// mutation does not replace low model, eventually pointers will be used.
newTitle := v3Doc.Model.Info.GoLow().Title.Mutate("The magic API - but now, altered!")
v3Doc.Model.Info.GoLow().Title = newTitle
assert.Equal(t, "The magic API - but now, altered!", v3Doc.Model.Info.GoLow().Title.Value)
serial, err := doc.Serialize() serial, err := doc.Serialize()
assert.NoError(t, err) assert.NoError(t, err)

View File

@@ -1,41 +0,0 @@
package main
//func main() {
//
// testData := `openapi: 3.0.1
//info:
// title: this is a title
// description: this is a description
//tags:
// - name: Tag A
// description: cake
// x-hack: true
// - name: Tag B
// description: coffee
// x-code: hack`
//
// data := []byte(testData)
// _ = ioutil.WriteFile("sample.yaml", data, 0664)
//
// info, _ := datamodel.ExtractSpecInfo(data)
// lowDoc, err := low.CreateDocument(info)
// if len(err) > 0 {
// for e := range err {
// fmt.Printf("%e\n", err[e])
// }
// return
// }
// highDoc := high.NewDocument(lowDoc)
//
// highDoc.Info.GoLow().Title.ValueNode.Value = "let's hack this"
// //highDoc.Tags[0].SetName("We are a new name now")
// //highDoc.Tags[0].SetDescription("and a new description")
//
// //newTag := lowDoc.AddTag()
// //fmt.Println(newTag)
// modified, _ := yaml.Marshal(info.RootNode)
// fmt.Println(string(modified))
//
// os.Remove("sample.yaml")
//
//}