Skip to content

Commit

Permalink
Working through test coverage
Browse files Browse the repository at this point in the history
This will be a bit of a slog, new code built in the hot path will need some love and attention.

Signed-off-by: quobix <dave@quobix.com>
  • Loading branch information
daveshanley committed Oct 24, 2023
1 parent 5d717bd commit c1cf240
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 124 deletions.
2 changes: 0 additions & 2 deletions datamodel/low/model_interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ type OpenAPIParameter interface {
//TODO: this needs to be fixed, move returns to pointers.

type SharedOperations interface {
//HasDescription
//HasExternalDocs
GetOperationId() NodeReference[string]
GetExternalDocs() NodeReference[any]
GetDescription() NodeReference[string]
Expand Down
2 changes: 1 addition & 1 deletion document_examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func ExampleNewDocument_fromWithDocumentConfigurationFailure() {
if len(errors) > 0 {
fmt.Println("Error building Digital Ocean spec errors reported")
}
// Output: There are 475 errors logged
// Output: There are 474 errors logged
//Error building Digital Ocean spec errors reported
}

Expand Down
89 changes: 14 additions & 75 deletions index/extract_refs.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
definitionPath = fmt.Sprintf("#/%s", strings.Join(loc, "/"))
fullDefinitionPath = fmt.Sprintf("%s#/%s", index.specAbsolutePath, strings.Join(loc, "/"))
_, jsonPath = utils.ConvertComponentIdIntoFriendlyPathSearch(definitionPath)
} else {
definitionPath = fmt.Sprintf("#/%s", n.Value)
fullDefinitionPath = fmt.Sprintf("%s#/%s", index.specAbsolutePath, n.Value)
_, jsonPath = utils.ConvertComponentIdIntoFriendlyPathSearch(definitionPath)
}
ref := &Reference{
FullDefinition: fullDefinitionPath,
Expand Down Expand Up @@ -110,12 +106,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
definitionPath = fmt.Sprintf("#/%s", strings.Join(loc, "/"))
fullDefinitionPath = fmt.Sprintf("%s#/%s", index.specAbsolutePath, strings.Join(loc, "/"))
_, jsonPath = utils.ConvertComponentIdIntoFriendlyPathSearch(definitionPath)
} else {
definitionPath = fmt.Sprintf("#/%s", n.Value)
fullDefinitionPath = fmt.Sprintf("%s#/%s", index.specAbsolutePath, n.Value)
_, jsonPath = utils.ConvertComponentIdIntoFriendlyPathSearch(definitionPath)
}

ref := &Reference{
FullDefinition: fullDefinitionPath,
Definition: definitionPath,
Expand Down Expand Up @@ -201,35 +192,16 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
copy(fp, seenPath)

value := node.Content[i+1].Value

segs := strings.Split(value, "/")
name := segs[len(segs)-1]

var p string
uri := strings.Split(value, "#/")

if strings.HasPrefix(value, "http") || filepath.IsAbs(value) {
if len(uri) == 2 {
_, p = utils.ConvertComponentIdIntoFriendlyPathSearch(fmt.Sprintf("#/%s", uri[1]))
} else {
_, p = utils.ConvertComponentIdIntoFriendlyPathSearch(uri[0])
}
} else {
if len(uri) == 2 {
_, p = utils.ConvertComponentIdIntoFriendlyPathSearch(fmt.Sprintf("#/%s", uri[1]))
} else {
_, p = utils.ConvertComponentIdIntoFriendlyPathSearch(value)
}
}

// determine absolute path to this definition

// TODO: come and clean this mess up.
var iroot string
var defRoot string
if strings.HasPrefix(index.specAbsolutePath, "http") {
iroot = index.specAbsolutePath
defRoot = index.specAbsolutePath
} else {
iroot = filepath.Dir(index.specAbsolutePath)
defRoot = filepath.Dir(index.specAbsolutePath)
}

var componentName string
Expand All @@ -255,8 +227,8 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
// if the index has a base path, use that to resolve the path
if index.config.BasePath != "" {
abs, _ := filepath.Abs(filepath.Join(index.config.BasePath, uri[0]))
if abs != iroot {
abs, _ = filepath.Abs(filepath.Join(iroot, uri[0]))
if abs != defRoot {
abs, _ = filepath.Abs(filepath.Join(defRoot, uri[0]))
}
fullDefinitionPath = fmt.Sprintf("%s#/%s", abs, uri[1])
componentName = fmt.Sprintf("#/%s", uri[1])
Expand All @@ -269,13 +241,6 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
u.Path = abs
fullDefinitionPath = fmt.Sprintf("%s#/%s", u.String(), uri[1])
componentName = fmt.Sprintf("#/%s", uri[1])

} else {

abs, _ := filepath.Abs(filepath.Join(iroot, uri[0]))
fullDefinitionPath = fmt.Sprintf("%s#/%s", abs, uri[1])
componentName = fmt.Sprintf("#/%s", uri[1])

}
}
}
Expand All @@ -287,29 +252,23 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
fullDefinitionPath = value
} else {
// is it a relative file include?
if strings.Contains(uri[0], "#") {
fullDefinitionPath = fmt.Sprintf("%s#/%s", iroot, uri[0])
componentName = fmt.Sprintf("#/%s", uri[0])
} else {
if !strings.Contains(uri[0], "#") {

if strings.HasPrefix(iroot, "http") {
if strings.HasPrefix(defRoot, "http") {
if !filepath.IsAbs(uri[0]) {
u, _ := url.Parse(iroot)
u, _ := url.Parse(defRoot)
pathDir := filepath.Dir(u.Path)
pathAbs, _ := filepath.Abs(filepath.Join(pathDir, uri[0]))
u.Path = pathAbs
fullDefinitionPath = u.String()
}
} else {
if filepath.IsAbs(uri[0]) {
fullDefinitionPath = uri[0]
} else {

if !filepath.IsAbs(uri[0]) {
// if the index has a base path, use that to resolve the path
if index.config.BasePath != "" {
abs, _ := filepath.Abs(filepath.Join(index.config.BasePath, uri[0]))
if abs != iroot {
abs, _ = filepath.Abs(filepath.Join(iroot, uri[0]))
if abs != defRoot {
abs, _ = filepath.Abs(filepath.Join(defRoot, uri[0]))
}
fullDefinitionPath = abs
componentName = uri[0]
Expand All @@ -325,7 +284,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,

} else {

abs, _ := filepath.Abs(filepath.Join(iroot, uri[0]))
abs, _ := filepath.Abs(filepath.Join(defRoot, uri[0]))
fullDefinitionPath = abs
componentName = uri[0]

Expand All @@ -338,6 +297,8 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
}
}

_, p := utils.ConvertComponentIdIntoFriendlyPathSearch(componentName)

ref := &Reference{
FullDefinition: fullDefinitionPath,
Definition: componentName,
Expand Down Expand Up @@ -598,10 +559,6 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc
located := index.FindComponent(ref.FullDefinition, ref.Node)
if located != nil {

if located.Index == nil {
index.logger.Warn("located component has no index", "component", located.FullDefinition)
}

index.refLock.Lock()
// have we already mapped this?
if index.allMappedRefs[ref.FullDefinition] == nil {
Expand All @@ -617,24 +574,6 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc
FullDefinition: ref.FullDefinition,
}
sequence[refIndex] = rm
} else {
// it exists, but is it a component with the same ID?
d := index.allMappedRefs[ref.FullDefinition]

// if the full definition matches, we're good and can skip this.
if d.FullDefinition != ref.FullDefinition {
found = append(found, located)
if located.FullDefinition != ref.FullDefinition {
located.FullDefinition = ref.FullDefinition
}
index.allMappedRefs[ref.FullDefinition] = located
rm := &ReferenceMapped{
Reference: located,
Definition: ref.Definition,
FullDefinition: ref.FullDefinition,
}
sequence[refIndex] = rm
}
}
index.refLock.Unlock()
} else {
Expand Down
39 changes: 9 additions & 30 deletions index/find_component.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,16 @@ func (index *SpecIndex) FindComponent(componentId string, parent *yaml.Node) *Re
return index.FindComponentInRoot(fmt.Sprintf("#/%s", uri[1]))
}
} else {
if !strings.Contains(componentId, "#") {

// does it contain a file extension?
fileExt := filepath.Ext(componentId)
if fileExt != "" {
return index.lookupRolodex(uri)
}
// does it contain a file extension?
fileExt := filepath.Ext(componentId)
if fileExt != "" {
return index.lookupRolodex(uri)
}

// root search
return index.FindComponentInRoot(componentId)
// root search
return index.FindComponentInRoot(componentId)

}
return index.FindComponentInRoot(fmt.Sprintf("#/%s", uri[0]))
}
}

Expand All @@ -72,12 +69,6 @@ func FindComponent(root *yaml.Node, componentId, absoluteFilePath string, index

fullDef := fmt.Sprintf("%s%s", absoluteFilePath, componentId)

// TODO: clean this shit up

newIndexWithUpdatedPath := *index
newIndexWithUpdatedPath.specAbsolutePath = absoluteFilePath
newIndexWithUpdatedPath.AbsoluteFile = absoluteFilePath

// extract properties
ref := &Reference{
FullDefinition: fullDef,
Expand All @@ -86,7 +77,7 @@ func FindComponent(root *yaml.Node, componentId, absoluteFilePath string, index
Node: resNode,
Path: friendlySearch,
RemoteLocation: absoluteFilePath,
Index: &newIndexWithUpdatedPath,
Index: index,
RequiredRefProperties: extractDefinitionRequiredRefProperties(resNode, map[string][]string{}, fullDef),
}

Expand Down Expand Up @@ -121,24 +112,12 @@ func (index *SpecIndex) lookupRolodex(uri []string) *Reference {
absoluteFileLocation = file
} else {
if index.specAbsolutePath != "" {
if index.config.BaseURL != nil {

// extract the base path from the specAbsolutePath for this index.
sap, _ := url.Parse(index.specAbsolutePath)
newPath, _ := filepath.Abs(filepath.Join(filepath.Dir(sap.Path), file))

sap.Path = newPath
f := sap.String()
absoluteFileLocation = f

} else {
if index.config.BaseURL == nil {

// consider the file local
dir := filepath.Dir(index.config.SpecAbsolutePath)
absoluteFileLocation, _ = filepath.Abs(filepath.Join(dir, file))
}
} else {
absoluteFileLocation = file
}
}

Expand Down
59 changes: 59 additions & 0 deletions index/find_component_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,58 @@ func TestSpecIndex_CheckCircularIndex(t *testing.T) {
assert.Nil(t, c)
}

func TestFindComponent_RolodexFileParseError(t *testing.T) {

badData := "I cannot be parsed: \"I am not a YAML file or a JSON file"
_ = os.WriteFile("bad.yaml", []byte(badData), 0644)
defer os.Remove("bad.yaml")

badRef := `openapi: 3.1.0
components:
schemas:
thing:
type: object
properties:
thong:
$ref: 'bad.yaml'
`
var rootNode yaml.Node
_ = yaml.Unmarshal([]byte(badRef), &rootNode)

cf := CreateOpenAPIIndexConfig()
cf.AvoidCircularReferenceCheck = true
cf.BasePath = "."

rolo := NewRolodex(cf)
rolo.SetRootNode(&rootNode)
cf.Rolodex = rolo

fsCfg := LocalFSConfig{
BaseDirectory: cf.BasePath,
FileFilters: []string{"bad.yaml"},
DirFS: os.DirFS(cf.BasePath),
}

fileFS, err := NewLocalFSWithConfig(&fsCfg)

assert.NoError(t, err)
rolo.AddLocalFS(cf.BasePath, fileFS)

indexedErr := rolo.IndexTheRolodex()
rolo.BuildIndexes()

// should error
assert.Error(t, indexedErr)

index := rolo.GetRootIndex()

assert.Nil(t, index.uri)

// can't be found.
a, _ := index.SearchIndexForReference("bad.yaml")
assert.Nil(t, a)
}

func TestSpecIndex_performExternalLookup_invalidURL(t *testing.T) {
yml := `openapi: 3.1.0
components:
Expand Down Expand Up @@ -105,6 +157,13 @@ components:
assert.Len(t, index.GetReferenceIndexErrors(), 0)
}

func TestSpecIndex_FailFindComponentInRoot(t *testing.T) {

index := &SpecIndex{}
assert.Nil(t, index.FindComponentInRoot("does it even matter? of course not. no"))

}

func TestSpecIndex_LocateRemoteDocsWithRemoteURLHandler(t *testing.T) {

// This test will push the index to do try and locate remote references that use relative references
Expand Down
15 changes: 0 additions & 15 deletions index/index_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,6 @@ func isHttpMethod(val string) bool {
return false
}

func DetermineReferenceResolveType(ref string) int {
if ref != "" && ref[0] == '#' {
return LocalResolve
}
if ref != "" && len(ref) >= 5 && (ref[:5] == "https" || ref[:5] == "http:") {
return HttpResolve
}
if strings.Contains(ref, ".json") ||
strings.Contains(ref, ".yaml") ||
strings.Contains(ref, ".yml") {
return FileResolve
}
return -1
}

func boostrapIndexCollections(rootNode *yaml.Node, index *SpecIndex) {
index.root = rootNode
index.allRefs = make(map[string]*Reference)
Expand Down
1 change: 0 additions & 1 deletion what-changed/model/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,6 @@ func CompareOperations(l, r any) *OperationChanges {
oc.ServerChanges = checkServers(lOperation.Servers, rOperation.Servers)
oc.ExtensionChanges = CompareExtensions(lOperation.Extensions, rOperation.Extensions)

// todo: callbacks
}
CheckProperties(props)
oc.PropertyChanges = NewPropertyChanges(changes)
Expand Down

0 comments on commit c1cf240

Please sign in to comment.