Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recreated bug with lineObjects being corrupted due to not accounting for $ref line numbers #8

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module github.com/pb33f/doctor

go 1.21.5
go 1.23

toolchain go1.23.0

require (
github.com/google/uuid v1.6.0
github.com/pb33f/libopenapi v0.16.14
github.com/sourcegraph/conc v0.3.0
github.com/stretchr/testify v1.8.4
github.com/stretchr/testify v1.9.0
golang.org/x/net v0.27.0
golang.org/x/text v0.16.0
gopkg.in/yaml.v3 v3.0.1
Expand All @@ -18,8 +20,10 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dprotaso/go-yit v0.0.0-20240618133044-5a0af90af097 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.9-0.20240815153524-6ea36470d1bd // indirect
)
2 changes: 1 addition & 1 deletion model/high/base/foundation.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func (f *Foundation) GenerateJSONPath() string {
return f.JSONPath
}
path := f.GenerateJSONPathWithLevel(0)
f.JSONPath = path
//f.JSONPath = path
return path
}

Expand Down
16 changes: 15 additions & 1 deletion model/walk_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/pb33f/libopenapi/index"
"github.com/sourcegraph/conc"
"gopkg.in/yaml.v3"
"reflect"
"sort"
"sync"
)
Expand All @@ -41,6 +42,9 @@ type DrDocument struct {
Edges []*drBase.Edge
index *index.SpecIndex
lineObjects map[int]any

// debugging code
lineObjectMisMatches int
}

type HasValue interface {
Expand Down Expand Up @@ -79,7 +83,8 @@ func (w *DrDocument) LocateModel(node *yaml.Node) (drBase.Foundational, error) {
if w.lineObjects[node.Line] == nil {
return nil, fmt.Errorf("model not found at line %d", node.Line)
}
return w.lineObjects[node.Line].(drBase.Foundational), nil
v := w.lineObjects[node.Line]
return v.(drBase.Foundational), nil
}

// LocateModelByLine finds the model represented by the line number of the supplied node.
Expand Down Expand Up @@ -342,6 +347,10 @@ func (w *DrDocument) walkV3(doc *v3.Document, buildGraph bool) *drV3.Document {
return drDoc
}

func sameType(x, y interface{}) bool {
return reflect.TypeOf(x) == reflect.TypeOf(y)
}

func (w *DrDocument) processObject(obj any, ln []any) {
if hv, ok := obj.(HasValue); ok {
if gl, ll := hv.GetValue().(high.GoesLowUntyped); ll {
Expand All @@ -356,6 +365,11 @@ func (w *DrDocument) processObject(obj any, ln []any) {
if ln != nil {
ln[k] = w.lineObjects[k]
}
} else {
if !sameType(w.lineObjects[k], obj) {
w.lineObjectMisMatches++
}
fmt.Printf("Line object %d already exists: +%T (%p) vs %T (%p). Is Equal?: %v Is the same type?: %v \n", k, obj, obj, w.lineObjects[k], w.lineObjects[k], reflect.DeepEqual(w.lineObjects[k], obj), sameType(w.lineObjects[k], obj))
}
}
}
Expand Down
34 changes: 34 additions & 0 deletions model/walk_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,40 @@ func TestWalker_TestBurgers(t *testing.T) {
assert.Equal(t, 31, len(walker.Schemas))
assert.Equal(t, 0, len(walker.SkippedSchemas))

}
func TestWalker_TestNestedBurgers(t *testing.T) {

// create a libopenapi document
var bytes []byte
var newDoc libopenapi.Document
measureExecutionTime("load", func() {
bytes, _ = os.ReadFile("../test_specs/nested/burgershop.openapi.yaml")
})

measureExecutionTime("new doc", func() {
newDoc, _ = libopenapi.NewDocument(bytes)
})

var v3Docs *libopenapi.DocumentModel[v3.Document]
measureExecutionTime("build model", func() {
config := &datamodel.DocumentConfiguration{
AllowFileReferences: false,
AllowRemoteReferences: false,
BasePath: "../test_specs/nested",
}
newDoc.SetConfiguration(config)
v3Docs, _ = newDoc.BuildV3Model()
})

var walker *DrDocument
measureExecutionTime("new walker", func() {
walker = NewDrDocument(v3Docs)
})

assert.Equal(t, 0, walker.lineObjectMisMatches) // This is failing because of $ref's messing up the line counting
assert.Equal(t, 31, len(walker.Schemas))
assert.Equal(t, 0, len(walker.SkippedSchemas))

}

func BenchmarkWalker_TestBurgers(b *testing.B) {
Expand Down
34 changes: 34 additions & 0 deletions test_specs/nested/burgers/burger-dressings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
get:
operationId: listBurgerDressings
tags:
- "Dressing"
summary: Get a list of all dressings available
description: Same as the summary, look up a tasty burger, by its ID - the burger identifier
parameters:
- in: path
name: burgerId
schema:
type: string
example: big-mac
description: the name of the our fantastic burger. You can pick a name from our menu
required: true
responses:
"200":
$ref: '../burgershop.openapi.yaml#/components/responses/DressingResponse'
"404":
description: Cannot find your burger in which to list dressings. Sorry
content:
application/json:
x-nice: rice
schema:
$ref: '../burgershop.openapi.yaml#/components/schemas/Error'
example:
message: There is no burger here
"500":
description: Unexpected error listing dressings for burger. Sorry.
content:
application/json:
schema:
$ref: '../burgershop.openapi.yaml#/components/schemas/Error'
example:
message: computer says no dressings for this burger.
55 changes: 55 additions & 0 deletions test_specs/nested/burgers/burger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
get:
callbacks:
burgerCallback:
$ref: '../burgershop.openapi.yaml#/components/callbacks/BurgerCallback'
operationId: locateBurger
tags:
- "Burgers"
summary: Search a burger by ID - returns the burger with that identifier
description: Look up a tasty burger take it and enjoy it
parameters:
- $ref: '../burgershop.openapi.yaml#/components/parameters/BurgerId'
- $ref: '../burgershop.openapi.yaml#/components/parameters/BurgerHeader'
responses:
"200":
description: A tasty burger for you to eat. Wide variety of products to choose from
content:
application/json:
schema:
$ref: '../burgershop.openapi.yaml#/components/schemas/Burger'
examples:
quarterPounder:
$ref: '../burgershop.openapi.yaml#/components/examples/QuarterPounder'
filetOFish:
summary: A tasty treat from the sea
value:
name: Filet-O-Fish
numPatties: 1
links:
ListBurgerDressings:
operationId: listBurgerDressings
parameters:
dressingId: 'something here'
description: 'Try the ketchup!'
"404":
description: Cannot find your burger. Sorry. We may have sold out of this type
content:
application/json:
schema:
$ref: '../burgershop.openapi.yaml#/components/schemas/Error'
examples:
notFound:
summary: burger missing
value:
message: can't find a burger with that ID, we may have sold out my friend.
"500":
description: Unexpected error. Sorry.
content:
application/json:
schema:
$ref: '../burgershop.openapi.yaml#/components/schemas/Error'
examples:
unexpectedError:
summary: oh my stars
value:
message: something went terribly wrong my friend, burger location crashed!
61 changes: 61 additions & 0 deletions test_specs/nested/burgers/burgers.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
x-burger-meta: meaty
post:
operationId: createBurger
tags:
- "Burgers"
summary: Create a new burger
description: A new burger for our menu, yummy yum yum.
requestBody:
$ref: '../burgershop.openapi.yaml#/components/requestBodies/BurgerRequest'
responses:
"200":
headers:
UseOil:
$ref: '../burgershop.openapi.yaml#/components/headers/UseOil'
description: A tasty burger for you to eat.
content:
application/json:
schema:
$ref: '../burgershop.openapi.yaml#/components/schemas/Burger'
examples:
quarterPounder:
$ref: '../burgershop.openapi.yaml#/components/examples/QuarterPounder'
filetOFish:
summary: a cripsy fish sammich filled with ocean goodness.
value:
name: Filet-O-Fish
numPatties: 1
links:
LocateBurger:
$ref: '../burgershop.openapi.yaml#/components/links/LocateBurger'
AnotherLocateBurger:
$ref: '../burgershop.openapi.yaml#/components/links/AnotherLocateBurger'
"500":
description: Unexpected error creating a new burger. Sorry.
content:
application/json:
schema:
$ref: '../burgershop.openapi.yaml#/components/schemas/Error'
examples:
unexpectedError:
summary: oh my goodness
value:
message: something went terribly wrong my friend, no new burger for you.
"422":
description: Unprocessable entity
content:
application/json:
schema:
$ref: '../burgershop.openapi.yaml#/components/schemas/Error'
examples:
unexpectedError:
summary: invalid request
value:
message: unable to accept this request, looks bad, missing something.
security:
- OAuthScheme:
- read:burgers
- write:burgers
servers:
- url: https://pb33f.io
description: this is an alternative server for this operation.
Loading