Skip to content

Commit

Permalink
flatten Default field (#432)
Browse files Browse the repository at this point in the history
fixes #431
  • Loading branch information
tcdsv authored Nov 15, 2023
1 parent 64f72a4 commit 82da6e2
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 2 deletions.
30 changes: 28 additions & 2 deletions flatten/merge_allof.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"math"
"reflect"
"regexp"
"strings"

Expand All @@ -13,7 +14,7 @@ import (
const (
FormatErrorMessage = "unable to resolve Format conflict using default resolver: all Format values must be identical"
TypeErrorMessage = "unable to resolve Type conflict: all Type values must be identical"
FormatResolverError = ""
DefaultErrorMessage = "unable to resolve Default conflict: all Default values must be identical"

FormatInt32 = "int32"
FormatInt64 = "int64"
Expand Down Expand Up @@ -50,6 +51,7 @@ type SchemaCollection struct {
Nullable []bool
ReadOnly []bool
WriteOnly []bool
Default []interface{}
}

type state struct {
Expand Down Expand Up @@ -137,6 +139,7 @@ func mergeInternal(state *state, base *openapi3.SchemaRef) (*openapi3.SchemaRef,
result.Value.Max = base.Value.Max
result.Value.MultipleOf = base.Value.MultipleOf
result.Value.MinLength = base.Value.MinLength
result.Value.Default = base.Value.Default
if base.Value.MaxLength != nil {
result.Value.MaxLength = openapi3.Uint64Ptr(*base.Value.MaxLength)
}
Expand Down Expand Up @@ -301,7 +304,10 @@ func flattenSchemas(state *state, result *openapi3.SchemaRef, schemas []*openapi
result.Value.Required = resolveRequired(collection.Required)
result.Value = resolveMultipleOf(result.Value, &collection)
result.Value.UniqueItems = resolveUniqueItems(collection.UniqueItems)

result.Value.Default, err = resolveDefault(&collection)
if err != nil {
return err
}
result.Value.Enum, err = resolveEnum(collection.Enum)
if err != nil {
return err
Expand Down Expand Up @@ -873,6 +879,7 @@ func collect(schemas []*openapi3.SchemaRef) SchemaCollection {
collection.Nullable = append(collection.Nullable, s.Value.Nullable)
collection.ReadOnly = append(collection.ReadOnly, s.Value.ReadOnly)
collection.WriteOnly = append(collection.WriteOnly, s.Value.WriteOnly)
collection.Default = append(collection.Default, s.Value.Default)
}
return collection
}
Expand Down Expand Up @@ -1008,3 +1015,22 @@ func findIntersection(arrays ...[]string) []string {

return intersection
}

func resolveDefault(collection *SchemaCollection) (interface{}, error) {
values := make([]interface{}, 0)
for _, v := range collection.Default {
if v != nil {
values = append(values, v)
}
}
if len(values) == 0 {
return nil, nil
}
first := values[0]
for _, v := range values {
if !reflect.DeepEqual(first, v) {
return nil, errors.New(DefaultErrorMessage)
}
}
return first, nil
}
121 changes: 121 additions & 0 deletions flatten/merge_allof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,127 @@ import (
"github.com/stretchr/testify/require"
)

// identical Default fields are merged successfully
func TestMerge_Default(t *testing.T) {
merged, err := flatten.Merge(
openapi3.SchemaRef{
Value: &openapi3.Schema{
Default: 10,
},
})

require.NoError(t, err)
require.Equal(t, 10, merged.Default)

merged, err = flatten.Merge(
openapi3.SchemaRef{
Value: &openapi3.Schema{
AllOf: openapi3.SchemaRefs{
&openapi3.SchemaRef{
Value: &openapi3.Schema{
Type: "object",
},
},
},
},
})

require.NoError(t, err)
require.Nil(t, merged.AllOf)
require.Equal(t, nil, merged.Default)

merged, err = flatten.Merge(
openapi3.SchemaRef{
Value: &openapi3.Schema{
AllOf: openapi3.SchemaRefs{
&openapi3.SchemaRef{
Value: &openapi3.Schema{
Type: "object",
Default: 10,
},
},
},
},
})

require.NoError(t, err)
require.Nil(t, merged.AllOf)
require.Equal(t, 10, merged.Default)

merged, err = flatten.Merge(
openapi3.SchemaRef{
Value: &openapi3.Schema{
AllOf: openapi3.SchemaRefs{
&openapi3.SchemaRef{
Value: &openapi3.Schema{
Type: "object",
Default: 10,
},
},
&openapi3.SchemaRef{
Value: &openapi3.Schema{
Type: "object",
Default: 10,
},
},
},
},
})

require.NoError(t, err)
require.Nil(t, merged.AllOf)
require.Equal(t, 10, merged.Default)

merged, err = flatten.Merge(
openapi3.SchemaRef{
Value: &openapi3.Schema{
AllOf: openapi3.SchemaRefs{
&openapi3.SchemaRef{
Value: &openapi3.Schema{
Type: "object",
Default: "abc",
},
},
&openapi3.SchemaRef{
Value: &openapi3.Schema{
Type: "object",
Default: "abc",
},
},
},
},
})

require.NoError(t, err)
require.Nil(t, merged.AllOf)
require.Equal(t, "abc", merged.Default)
}

// Conflicting Default values cannot be resolved
func TestMerge_DefaultFailure(t *testing.T) {
_, err := flatten.Merge(
openapi3.SchemaRef{
Value: &openapi3.Schema{
AllOf: openapi3.SchemaRefs{
&openapi3.SchemaRef{
Value: &openapi3.Schema{
Type: "object",
Default: 10,
},
},
&openapi3.SchemaRef{
Value: &openapi3.Schema{
Type: "object",
Default: "abc",
},
},
},
},
})

require.EqualError(t, err, flatten.DefaultErrorMessage)
}

// verify that if all ReadOnly fields are set to false, then the ReadOnly field in the merged schema is false.
func TestMerge_ReadOnlyIsSetToFalse(t *testing.T) {
merged, err := flatten.Merge(
Expand Down

0 comments on commit 82da6e2

Please sign in to comment.