mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 12:37:49 +00:00
@@ -4,6 +4,7 @@
|
|||||||
package high
|
package high
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -16,11 +17,12 @@ import (
|
|||||||
|
|
||||||
// NodeEntry represents a single node used by NodeBuilder.
|
// NodeEntry represents a single node used by NodeBuilder.
|
||||||
type NodeEntry struct {
|
type NodeEntry struct {
|
||||||
Tag string
|
Tag string
|
||||||
Key string
|
Key string
|
||||||
Value any
|
Value any
|
||||||
Line int
|
StringValue string
|
||||||
RenderZero bool
|
Line int
|
||||||
|
RenderZero bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeBuilder is a structure used by libopenapi high-level objects, to render themselves back to YAML.
|
// NodeBuilder is a structure used by libopenapi high-level objects, to render themselves back to YAML.
|
||||||
@@ -131,8 +133,11 @@ func (n *NodeBuilder) add(key string, i int) {
|
|||||||
switch value.Kind() {
|
switch value.Kind() {
|
||||||
case reflect.Float64, reflect.Float32:
|
case reflect.Float64, reflect.Float32:
|
||||||
nodeEntry.Value = value.Float()
|
nodeEntry.Value = value.Float()
|
||||||
|
x := float64(int(value.Float()*100)) / 100 // trim this down
|
||||||
|
nodeEntry.StringValue = strconv.FormatFloat(x, 'f', -1, 64)
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
nodeEntry.Value = value.Int()
|
nodeEntry.Value = value.Int()
|
||||||
|
nodeEntry.StringValue = value.String()
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
nodeEntry.Value = value.String()
|
nodeEntry.Value = value.String()
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
@@ -316,7 +321,13 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, entry *NodeEntry) *yaml.Nod
|
|||||||
break
|
break
|
||||||
|
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
val := strconv.FormatFloat(value.(float64), 'f', -1, 64)
|
|
||||||
|
precision := -1
|
||||||
|
if entry.StringValue != "" && strings.Contains(entry.StringValue, ".") {
|
||||||
|
precision = len(strings.Split(fmt.Sprint(entry.StringValue), ".")[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
val := strconv.FormatFloat(value.(float64), 'f', precision, 64)
|
||||||
valueNode = utils.CreateFloatNode(val)
|
valueNode = utils.CreateFloatNode(val)
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
break
|
break
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,31 +4,31 @@
|
|||||||
package datamodel
|
package datamodel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// OpenApi3 is used by all OpenAPI 3+ docs
|
// OpenApi3 is used by all OpenAPI 3+ docs
|
||||||
OpenApi3 = "openapi"
|
OpenApi3 = "openapi"
|
||||||
|
|
||||||
// OpenApi2 is used by all OpenAPI 2 docs, formerly known as swagger.
|
// OpenApi2 is used by all OpenAPI 2 docs, formerly known as swagger.
|
||||||
OpenApi2 = "swagger"
|
OpenApi2 = "swagger"
|
||||||
|
|
||||||
// AsyncApi is used by akk AsyncAPI docs, all versions.
|
// AsyncApi is used by akk AsyncAPI docs, all versions.
|
||||||
AsyncApi = "asyncapi"
|
AsyncApi = "asyncapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSpecInfo_GetJSONParsingChannel(t *testing.T) {
|
func TestSpecInfo_GetJSONParsingChannel(t *testing.T) {
|
||||||
|
|
||||||
// dumb, but we need to ensure coverage is as high as we can make it.
|
// dumb, but we need to ensure coverage is as high as we can make it.
|
||||||
bchan := make(chan bool)
|
bchan := make(chan bool)
|
||||||
si := &SpecInfo{JsonParsingChannel: bchan}
|
si := &SpecInfo{JsonParsingChannel: bchan}
|
||||||
assert.Equal(t, si.GetJSONParsingChannel(), bchan)
|
assert.Equal(t, si.GetJSONParsingChannel(), bchan)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,147 +115,147 @@ info:
|
|||||||
version: '0.1.0'`
|
version: '0.1.0'`
|
||||||
|
|
||||||
func TestExtractSpecInfo_ValidJSON(t *testing.T) {
|
func TestExtractSpecInfo_ValidJSON(t *testing.T) {
|
||||||
r, e := ExtractSpecInfo([]byte(goodJSON))
|
r, e := ExtractSpecInfo([]byte(goodJSON))
|
||||||
assert.Greater(t, len(*r.SpecJSONBytes), 0)
|
assert.Greater(t, len(*r.SpecJSONBytes), 0)
|
||||||
assert.Error(t, e)
|
assert.Error(t, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_InvalidJSON(t *testing.T) {
|
func TestExtractSpecInfo_InvalidJSON(t *testing.T) {
|
||||||
_, e := ExtractSpecInfo([]byte(badJSON))
|
_, e := ExtractSpecInfo([]byte(badJSON))
|
||||||
assert.Error(t, e)
|
assert.Error(t, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_Nothing(t *testing.T) {
|
func TestExtractSpecInfo_Nothing(t *testing.T) {
|
||||||
_, e := ExtractSpecInfo([]byte(""))
|
_, e := ExtractSpecInfo([]byte(""))
|
||||||
assert.Error(t, e)
|
assert.Error(t, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_ValidYAML(t *testing.T) {
|
func TestExtractSpecInfo_ValidYAML(t *testing.T) {
|
||||||
r, e := ExtractSpecInfo([]byte(goodYAML))
|
r, e := ExtractSpecInfo([]byte(goodYAML))
|
||||||
assert.Greater(t, len(*r.SpecJSONBytes), 0)
|
assert.Greater(t, len(*r.SpecJSONBytes), 0)
|
||||||
assert.Error(t, e)
|
assert.Error(t, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_InvalidYAML(t *testing.T) {
|
func TestExtractSpecInfo_InvalidYAML(t *testing.T) {
|
||||||
_, e := ExtractSpecInfo([]byte(badYAML))
|
_, e := ExtractSpecInfo([]byte(badYAML))
|
||||||
assert.Error(t, e)
|
assert.Error(t, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_InvalidOpenAPIVersion(t *testing.T) {
|
func TestExtractSpecInfo_InvalidOpenAPIVersion(t *testing.T) {
|
||||||
_, e := ExtractSpecInfo([]byte(OpenApiOne))
|
_, e := ExtractSpecInfo([]byte(OpenApiOne))
|
||||||
assert.Error(t, e)
|
assert.Error(t, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_OpenAPI3(t *testing.T) {
|
func TestExtractSpecInfo_OpenAPI3(t *testing.T) {
|
||||||
|
|
||||||
r, e := ExtractSpecInfo([]byte(OpenApi3Spec))
|
r, e := ExtractSpecInfo([]byte(OpenApi3Spec))
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
assert.Equal(t, utils.OpenApi3, r.SpecType)
|
assert.Equal(t, utils.OpenApi3, r.SpecType)
|
||||||
assert.Equal(t, "3.0.1", r.Version)
|
assert.Equal(t, "3.0.1", r.Version)
|
||||||
assert.Greater(t, len(*r.SpecJSONBytes), 0)
|
assert.Greater(t, len(*r.SpecJSONBytes), 0)
|
||||||
assert.Contains(t, r.APISchema, "https://spec.openapis.org/oas/3.0/schema/2021-09-28")
|
assert.Contains(t, r.APISchema, "https://spec.openapis.org/oas/3.0/schema/2021-09-28")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_OpenAPIWat(t *testing.T) {
|
func TestExtractSpecInfo_OpenAPIWat(t *testing.T) {
|
||||||
|
|
||||||
r, e := ExtractSpecInfo([]byte(OpenApiWat))
|
r, e := ExtractSpecInfo([]byte(OpenApiWat))
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
assert.Equal(t, OpenApi3, r.SpecType)
|
assert.Equal(t, OpenApi3, r.SpecType)
|
||||||
assert.Equal(t, "3.2", r.Version)
|
assert.Equal(t, "3.2", r.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_OpenAPI31(t *testing.T) {
|
func TestExtractSpecInfo_OpenAPI31(t *testing.T) {
|
||||||
|
|
||||||
r, e := ExtractSpecInfo([]byte(OpenApi31))
|
r, e := ExtractSpecInfo([]byte(OpenApi31))
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
assert.Equal(t, OpenApi3, r.SpecType)
|
assert.Equal(t, OpenApi3, r.SpecType)
|
||||||
assert.Equal(t, "3.1", r.Version)
|
assert.Equal(t, "3.1", r.Version)
|
||||||
assert.Contains(t, r.APISchema, "https://spec.openapis.org/oas/3.1/schema/2022-02-27")
|
assert.Contains(t, r.APISchema, "https://spec.openapis.org/oas/3.1/schema/2022-10-07")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_OpenAPIFalse(t *testing.T) {
|
func TestExtractSpecInfo_OpenAPIFalse(t *testing.T) {
|
||||||
|
|
||||||
spec, e := ExtractSpecInfo([]byte(OpenApiFalse))
|
spec, e := ExtractSpecInfo([]byte(OpenApiFalse))
|
||||||
assert.NoError(t, e)
|
assert.NoError(t, e)
|
||||||
assert.Equal(t, "false", spec.Version)
|
assert.Equal(t, "false", spec.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_OpenAPI2(t *testing.T) {
|
func TestExtractSpecInfo_OpenAPI2(t *testing.T) {
|
||||||
|
|
||||||
r, e := ExtractSpecInfo([]byte(OpenApi2Spec))
|
r, e := ExtractSpecInfo([]byte(OpenApi2Spec))
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
assert.Equal(t, OpenApi2, r.SpecType)
|
assert.Equal(t, OpenApi2, r.SpecType)
|
||||||
assert.Equal(t, "2.0.1", r.Version)
|
assert.Equal(t, "2.0.1", r.Version)
|
||||||
assert.Greater(t, len(*r.SpecJSONBytes), 0)
|
assert.Greater(t, len(*r.SpecJSONBytes), 0)
|
||||||
assert.Contains(t, r.APISchema, "http://swagger.io/v2/schema.json#")
|
assert.Contains(t, r.APISchema, "http://swagger.io/v2/schema.json#")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_OpenAPI2_OddVersion(t *testing.T) {
|
func TestExtractSpecInfo_OpenAPI2_OddVersion(t *testing.T) {
|
||||||
|
|
||||||
_, e := ExtractSpecInfo([]byte(OpenApi2SpecOdd))
|
_, e := ExtractSpecInfo([]byte(OpenApi2SpecOdd))
|
||||||
assert.NotNil(t, e)
|
assert.NotNil(t, e)
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"spec is defined as a swagger (openapi 2.0) spec, but is an openapi 3 or unknown version", e.Error())
|
"spec is defined as a swagger (openapi 2.0) spec, but is an openapi 3 or unknown version", e.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_AsyncAPI(t *testing.T) {
|
func TestExtractSpecInfo_AsyncAPI(t *testing.T) {
|
||||||
|
|
||||||
r, e := ExtractSpecInfo([]byte(AsyncAPISpec))
|
r, e := ExtractSpecInfo([]byte(AsyncAPISpec))
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
assert.Equal(t, AsyncApi, r.SpecType)
|
assert.Equal(t, AsyncApi, r.SpecType)
|
||||||
assert.Equal(t, "2.0.0", r.Version)
|
assert.Equal(t, "2.0.0", r.Version)
|
||||||
assert.Greater(t, len(*r.SpecJSONBytes), 0)
|
assert.Greater(t, len(*r.SpecJSONBytes), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_AsyncAPI_OddVersion(t *testing.T) {
|
func TestExtractSpecInfo_AsyncAPI_OddVersion(t *testing.T) {
|
||||||
|
|
||||||
_, e := ExtractSpecInfo([]byte(AsyncAPISpecOdd))
|
_, e := ExtractSpecInfo([]byte(AsyncAPISpecOdd))
|
||||||
assert.NotNil(t, e)
|
assert.NotNil(t, e)
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"spec is defined as asyncapi, but has a major version that is invalid", e.Error())
|
"spec is defined as asyncapi, but has a major version that is invalid", e.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_BadVersion_OpenAPI3(t *testing.T) {
|
func TestExtractSpecInfo_BadVersion_OpenAPI3(t *testing.T) {
|
||||||
|
|
||||||
yml := `openapi:
|
yml := `openapi:
|
||||||
should: fail`
|
should: fail`
|
||||||
|
|
||||||
_, err := ExtractSpecInfo([]byte(yml))
|
_, err := ExtractSpecInfo([]byte(yml))
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_BadVersion_Swagger(t *testing.T) {
|
func TestExtractSpecInfo_BadVersion_Swagger(t *testing.T) {
|
||||||
|
|
||||||
yml := `swagger:
|
yml := `swagger:
|
||||||
should: fail`
|
should: fail`
|
||||||
|
|
||||||
_, err := ExtractSpecInfo([]byte(yml))
|
_, err := ExtractSpecInfo([]byte(yml))
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractSpecInfo_BadVersion_AsyncAPI(t *testing.T) {
|
func TestExtractSpecInfo_BadVersion_AsyncAPI(t *testing.T) {
|
||||||
|
|
||||||
yml := `asyncapi:
|
yml := `asyncapi:
|
||||||
should: fail`
|
should: fail`
|
||||||
|
|
||||||
_, err := ExtractSpecInfo([]byte(yml))
|
_, err := ExtractSpecInfo([]byte(yml))
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleExtractSpecInfo() {
|
func ExampleExtractSpecInfo() {
|
||||||
|
|
||||||
// load bytes from openapi spec file.
|
// load bytes from openapi spec file.
|
||||||
bytes, _ := ioutil.ReadFile("../test_specs/petstorev3.json")
|
bytes, _ := ioutil.ReadFile("../test_specs/petstorev3.json")
|
||||||
|
|
||||||
// create a new *SpecInfo instance from loaded bytes
|
// create a new *SpecInfo instance from loaded bytes
|
||||||
specInfo, err := ExtractSpecInfo(bytes)
|
specInfo, err := ExtractSpecInfo(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("cannot extract spec info: %e", err))
|
panic(fmt.Sprintf("cannot extract spec info: %e", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// print out the version, format and filetype
|
// print out the version, format and filetype
|
||||||
fmt.Printf("the version of the spec is %s, the format is %s and the file type is %s",
|
fmt.Printf("the version of the spec is %s, the format is %s and the file type is %s",
|
||||||
specInfo.Version, specInfo.SpecFormat, specInfo.SpecFileType)
|
specInfo.Version, specInfo.SpecFormat, specInfo.SpecFileType)
|
||||||
|
|
||||||
// Output: the version of the spec is 3.0.2, the format is oas3 and the file type is json
|
// Output: the version of the spec is 3.0.2, the format is oas3 and the file type is json
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -665,5 +665,5 @@ func ExampleNewDocument_modifyAndReRender() {
|
|||||||
fmt.Printf("There were %d original paths. There are now %d paths in the document\n", originalPaths, newPaths)
|
fmt.Printf("There were %d original paths. There are now %d paths in the document\n", originalPaths, newPaths)
|
||||||
fmt.Printf("The original spec had %d bytes, the new one has %d\n", len(petstore), len(rawBytes))
|
fmt.Printf("The original spec had %d bytes, the new one has %d\n", len(petstore), len(rawBytes))
|
||||||
// Output: There were 13 original paths. There are now 14 paths in the document
|
// Output: There were 13 original paths. There are now 14 paths in the document
|
||||||
//The original spec had 31143 bytes, the new one has 27857
|
//The original spec had 31143 bytes, the new one has 27841
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user