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
9 changes: 9 additions & 0 deletions internal/sliceutil/sliceutil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package sliceutil

func Map[T any, U any](slice []T, fn func(T) U) []U {
mapped := make([]U, len(slice))
for i, elem := range slice {
mapped[i] = fn(elem)
}
return mapped
}
44 changes: 44 additions & 0 deletions internal/sliceutil/sliceutil_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package sliceutil_test

import (
"testing"

"github.com/speakeasy-api/openapi/internal/sliceutil"
"github.com/stretchr/testify/assert"
)

func TestMap(t *testing.T) {
t.Parallel()
tests := []struct {
name string
slice []int
fn func(int) int
expected []int
}{
{
name: "empty slice",
slice: []int{},
fn: func(i int) int { return i },
expected: []int{},
},
{
name: "single element",
slice: []int{1},
fn: func(i int) int { return i },
expected: []int{1},
},
{
name: "multiple elements",
slice: []int{1, 2, 3},
fn: func(i int) int { return i },
expected: []int{1, 2, 3},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
result := sliceutil.Map(tt.slice, tt.fn)
assert.Equal(t, tt.expected, result)
})
}
}
12 changes: 12 additions & 0 deletions internal/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ func (v Version) LessThan(other Version) bool {
return !v.Equal(other) && !v.GreaterThan(other)
}

func (v Version) IsOneOf(versions []*Version) bool {
for _, ver := range versions {
if ver == nil {
continue
}
if v.Equal(*ver) {
return true
}
}
return false
}

func Parse(version string) (*Version, error) {
parts := strings.Split(version, ".")
if len(parts) != 3 {
Expand Down
91 changes: 91 additions & 0 deletions internal/version/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,94 @@ func Test_ParseVersion_Error(t *testing.T) {
})
}
}

func Test_Version_IsOneOf(t *testing.T) {
t.Parallel()
tests := []struct {
name string
version Version
versions []*Version
expected bool
}{
{
name: "version is in list",
version: Version{Major: 1, Minor: 2, Patch: 3},
versions: []*Version{
{Major: 1, Minor: 0, Patch: 0},
{Major: 1, Minor: 2, Patch: 3},
{Major: 2, Minor: 0, Patch: 0},
},
expected: true,
},
{
name: "version is not in list",
version: Version{Major: 1, Minor: 2, Patch: 3},
versions: []*Version{
{Major: 1, Minor: 0, Patch: 0},
{Major: 1, Minor: 2, Patch: 4},
{Major: 2, Minor: 0, Patch: 0},
},
expected: false,
},
{
name: "empty list",
version: Version{Major: 1, Minor: 2, Patch: 3},
versions: []*Version{},
expected: false,
},
{
name: "nil list",
version: Version{Major: 1, Minor: 2, Patch: 3},
versions: nil,
expected: false,
},
{
name: "list with nil values",
version: Version{Major: 1, Minor: 2, Patch: 3},
versions: []*Version{
nil,
{Major: 1, Minor: 2, Patch: 3},
nil,
},
expected: true,
},
{
name: "version is first in list",
version: Version{Major: 1, Minor: 0, Patch: 0},
versions: []*Version{
{Major: 1, Minor: 0, Patch: 0},
{Major: 1, Minor: 2, Patch: 3},
{Major: 2, Minor: 0, Patch: 0},
},
expected: true,
},
{
name: "version is last in list",
version: Version{Major: 2, Minor: 0, Patch: 0},
versions: []*Version{
{Major: 1, Minor: 0, Patch: 0},
{Major: 1, Minor: 2, Patch: 3},
{Major: 2, Minor: 0, Patch: 0},
},
expected: true,
},
{
name: "similar but different versions",
version: Version{Major: 1, Minor: 2, Patch: 3},
versions: []*Version{
{Major: 1, Minor: 2, Patch: 2},
{Major: 1, Minor: 2, Patch: 4},
{Major: 1, Minor: 3, Patch: 3},
},
expected: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
result := tt.version.IsOneOf(tt.versions)
assert.Equal(t, tt.expected, result)
})
}
}
43 changes: 38 additions & 5 deletions overlay/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ import (
"fmt"
"net/url"
"strings"

"github.com/speakeasy-api/openapi/internal/sliceutil"
"github.com/speakeasy-api/openapi/internal/version"
)

var (
SupportedVersions = []*version.Version{version.MustParse("1.0.0"), version.MustParse("1.1.0")}
)

// Errors
var (
ErrOverlayVersionInvalid = errors.New("overlay version is invalid")
ErrOverlayVersionNotSupported = fmt.Errorf("overlay version must be one of: %s", strings.Join(sliceutil.Map(SupportedVersions, func(v *version.Version) string { return v.String() }), ", "))
ErrOverlayVersionMustBeDefined = errors.New("overlay version must be defined")
ErrOverlayInfoTitleMustBeDefined = errors.New("overlay info title must be defined")
ErrOverlayInfoVersionMustBeDefined = errors.New("overlay info version must be defined")
ErrOverlayExtendsMustBeAValidURL = errors.New("overlay extends must be a valid URL")
ErrOverlayMustDefineAtLeastOneAction = errors.New("overlay must define at least one action")
ErrOverlayActionTargetMustBeDefined = errors.New("overlay action target must be defined")
ErrOverlayActionRemoveAndUpdateCannotBeSet = errors.New("overlay action remove and update cannot be set")
)

type ValidationErrors []error
Expand All @@ -24,18 +44,31 @@ func (v ValidationErrors) Return() error {
return nil
}

func (o *Overlay) ValidateVersion() []error {
errs := make(ValidationErrors, 0)
overlayVersion, err := version.Parse(o.Version)
switch {
case err != nil || overlayVersion == nil:
errs = append(errs, ErrOverlayVersionInvalid)
case !overlayVersion.IsOneOf(SupportedVersions):
errs = append(errs, ErrOverlayVersionNotSupported)
}

return errs
}

func (o *Overlay) Validate() error {
errs := make(ValidationErrors, 0)
if o.Version != "1.0.0" {
errs = append(errs, errors.New("overlay version must be 1.0.0"))

errs = append(errs, o.ValidateVersion()...)

if o.Info.Version == "" {
errs = append(errs, errors.New("overlay info version must be defined"))
}

if o.Info.Title == "" {
errs = append(errs, errors.New("overlay info title must be defined"))
}
if o.Info.Version == "" {
errs = append(errs, errors.New("overlay info version must be defined"))
}

if o.Extends != "" {
_, err := url.Parse(o.Extends)
Expand Down
Loading
Loading