Skip to content
Merged
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
289 changes: 289 additions & 0 deletions datamodel/low/base/build_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
// Copyright 2022-2026 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT

package base

import (
"context"
"testing"

"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"go.yaml.in/yaml/v4"
)

func benchmarkInfoRootNode(b *testing.B) *yaml.Node {
b.Helper()

yml := `title: Pizza API
summary: pizza summary
description: pizza description
termsOfService: https://example.com/tos
contact:
name: Pizza Team
url: https://example.com/contact
email: pizza@example.com
license:
name: MIT
url: https://example.com/license
version: 1.0.0
x-info:
hot: true`

var root yaml.Node
if err := yaml.Unmarshal([]byte(yml), &root); err != nil {
b.Fatalf("failed to unmarshal benchmark info: %v", err)
}
if len(root.Content) == 0 || root.Content[0] == nil {
b.Fatal("failed to unmarshal benchmark info: empty root")
}
return root.Content[0]
}

func benchmarkContactRootNode(b *testing.B) *yaml.Node {
b.Helper()

yml := `name: Pizza Team
url: https://example.com/contact
email: pizza@example.com
x-contact:
warm: true`

var root yaml.Node
if err := yaml.Unmarshal([]byte(yml), &root); err != nil {
b.Fatalf("failed to unmarshal benchmark contact: %v", err)
}
if len(root.Content) == 0 || root.Content[0] == nil {
b.Fatal("failed to unmarshal benchmark contact: empty root")
}
return root.Content[0]
}

func benchmarkLicenseRootNode(b *testing.B) *yaml.Node {
b.Helper()

yml := `name: Apache-2.0
url: https://example.com/license
x-license:
approved: true`

var root yaml.Node
if err := yaml.Unmarshal([]byte(yml), &root); err != nil {
b.Fatalf("failed to unmarshal benchmark license: %v", err)
}
if len(root.Content) == 0 || root.Content[0] == nil {
b.Fatal("failed to unmarshal benchmark license: empty root")
}
return root.Content[0]
}

func benchmarkExternalDocRootNode(b *testing.B) *yaml.Node {
b.Helper()

yml := `description: more docs
url: https://example.com/docs
x-docs:
bright: true`

var root yaml.Node
if err := yaml.Unmarshal([]byte(yml), &root); err != nil {
b.Fatalf("failed to unmarshal benchmark external doc: %v", err)
}
if len(root.Content) == 0 || root.Content[0] == nil {
b.Fatal("failed to unmarshal benchmark external doc: empty root")
}
return root.Content[0]
}

func benchmarkXMLRootNode(b *testing.B) *yaml.Node {
b.Helper()

yml := `name: item
namespace: https://example.com/ns
prefix: ex
attribute: false
nodeType: element
wrapped: true
x-xml:
rich: true`

var root yaml.Node
if err := yaml.Unmarshal([]byte(yml), &root); err != nil {
b.Fatalf("failed to unmarshal benchmark xml: %v", err)
}
if len(root.Content) == 0 || root.Content[0] == nil {
b.Fatal("failed to unmarshal benchmark xml: empty root")
}
return root.Content[0]
}

func benchmarkSecurityRequirementRootNode(b *testing.B) *yaml.Node {
b.Helper()

yml := `oauth:
- read
- write
apiKey:
- admin`

var root yaml.Node
if err := yaml.Unmarshal([]byte(yml), &root); err != nil {
b.Fatalf("failed to unmarshal benchmark security requirement: %v", err)
}
if len(root.Content) == 0 || root.Content[0] == nil {
b.Fatal("failed to unmarshal benchmark security requirement: empty root")
}
return root.Content[0]
}

func benchmarkTagRootNode(b *testing.B) *yaml.Node {
b.Helper()

yml := `name: partner
summary: Partner API
description: Operations available to the partners network
parent: external
kind: audience
externalDocs:
url: https://example.com/docs
description: more docs
x-tag:
warm: true`

var root yaml.Node
if err := yaml.Unmarshal([]byte(yml), &root); err != nil {
b.Fatalf("failed to unmarshal benchmark tag: %v", err)
}
if len(root.Content) == 0 || root.Content[0] == nil {
b.Fatal("failed to unmarshal benchmark tag: empty root")
}
return root.Content[0]
}

func BenchmarkInfo_Build(b *testing.B) {
rootNode := benchmarkInfoRootNode(b)
idx := index.NewSpecIndex(rootNode)
ctx := context.Background()

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
var info Info
if err := low.BuildModel(rootNode, &info); err != nil {
b.Fatalf("build model failed: %v", err)
}
if err := info.Build(ctx, nil, rootNode, idx); err != nil {
b.Fatalf("info build failed: %v", err)
}
}
}

func BenchmarkContact_Build(b *testing.B) {
rootNode := benchmarkContactRootNode(b)
idx := index.NewSpecIndex(rootNode)
ctx := context.Background()

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
var contact Contact
if err := low.BuildModel(rootNode, &contact); err != nil {
b.Fatalf("build model failed: %v", err)
}
if err := contact.Build(ctx, nil, rootNode, idx); err != nil {
b.Fatalf("contact build failed: %v", err)
}
}
}

func BenchmarkLicense_Build(b *testing.B) {
rootNode := benchmarkLicenseRootNode(b)
idx := index.NewSpecIndex(rootNode)
ctx := context.Background()

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
var license License
if err := low.BuildModel(rootNode, &license); err != nil {
b.Fatalf("build model failed: %v", err)
}
if err := license.Build(ctx, nil, rootNode, idx); err != nil {
b.Fatalf("license build failed: %v", err)
}
}
}

func BenchmarkExternalDoc_Build(b *testing.B) {
rootNode := benchmarkExternalDocRootNode(b)
idx := index.NewSpecIndex(rootNode)
ctx := context.Background()

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
var ex ExternalDoc
if err := low.BuildModel(rootNode, &ex); err != nil {
b.Fatalf("build model failed: %v", err)
}
if err := ex.Build(ctx, nil, rootNode, idx); err != nil {
b.Fatalf("external doc build failed: %v", err)
}
}
}

func BenchmarkXML_Build(b *testing.B) {
rootNode := benchmarkXMLRootNode(b)
idx := index.NewSpecIndex(rootNode)

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
var x XML
if err := low.BuildModel(rootNode, &x); err != nil {
b.Fatalf("build model failed: %v", err)
}
if err := x.Build(rootNode, idx); err != nil {
b.Fatalf("xml build failed: %v", err)
}
}
}

func BenchmarkSecurityRequirement_Build(b *testing.B) {
rootNode := benchmarkSecurityRequirementRootNode(b)
ctx := context.Background()

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
var req SecurityRequirement
if err := req.Build(ctx, nil, rootNode, nil); err != nil {
b.Fatalf("security requirement build failed: %v", err)
}
}
}

func BenchmarkTag_Build(b *testing.B) {
rootNode := benchmarkTagRootNode(b)
idx := index.NewSpecIndex(rootNode)
ctx := context.Background()

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
var tag Tag
if err := low.BuildModel(rootNode, &tag); err != nil {
b.Fatalf("build model failed: %v", err)
}
if err := tag.Build(ctx, nil, rootNode, idx); err != nil {
b.Fatalf("tag build failed: %v", err)
}
}
}
22 changes: 19 additions & 3 deletions datamodel/low/base/contact.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
// Copyright 2022-2026 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT

package base

import (
"context"
"hash/maphash"
"sync"

"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
Expand All @@ -26,15 +27,30 @@ type Contact struct {
RootNode *yaml.Node
index *index.SpecIndex
context context.Context
nodeStore sync.Map
reference low.Reference
*low.Reference
low.NodeMap
}

func (c *Contact) Build(ctx context.Context, keyNode, root *yaml.Node, idx *index.SpecIndex) error {
c.KeyNode = keyNode
c.RootNode = root
c.Reference = new(low.Reference)
c.Nodes = low.ExtractNodes(ctx, root)
c.reference = low.Reference{}
c.Reference = &c.reference
c.nodeStore = sync.Map{}
c.Nodes = &c.nodeStore
if root == nil {
c.Extensions = nil
c.context = ctx
c.index = idx
return nil
}
if len(root.Content) > 0 {
c.NodeMap.ExtractNodes(root, false)
} else {
c.AddNode(root.Line, root)
}
c.Extensions = low.ExtractExtensions(root)
c.context = ctx
c.index = idx
Expand Down
18 changes: 17 additions & 1 deletion datamodel/low/base/contact_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
// Copyright 2022-2026 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT

package base
Expand Down Expand Up @@ -44,3 +44,19 @@ x-beer: cold`
assert.Nil(t, c.GetIndex())
assert.NotNil(t, c.GetContext())
}

func TestContact_Build_ScalarRoot(t *testing.T) {
var scalar yaml.Node
_ = yaml.Unmarshal([]byte("hello"), &scalar)

var c Contact
err := low.BuildModel(scalar.Content[0], &c)
assert.NoError(t, err)

err = c.Build(context.Background(), nil, scalar.Content[0], nil)
assert.NoError(t, err)

nodes := c.GetNodes()
assert.Len(t, nodes[scalar.Content[0].Line], 1)
assert.Equal(t, "hello", nodes[scalar.Content[0].Line][0].Value)
}
Loading
Loading