-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(refactor): rearrange some code and test files
- Loading branch information
Showing
7 changed files
with
525 additions
and
450 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package deckformat | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/kong/go-apiops/jsonbasics" | ||
) | ||
|
||
// | ||
// | ||
// section on compatibility and versioning between deckfiles | ||
// | ||
// | ||
|
||
// CompatibleTransform checks if 2 files are compatible, by '_transform' keys. | ||
// Returns nil if compatible, and error otherwise. | ||
func CompatibleTransform(data1 map[string]interface{}, data2 map[string]interface{}) error { | ||
if data1 == nil { | ||
panic("expected 'data1' to be non-nil") | ||
} | ||
if data2 == nil { | ||
panic("expected 'data2' to be non-nil") | ||
} | ||
|
||
transform1 := true // this is the default value | ||
if data1[TransformKey] != nil { | ||
var err error | ||
if transform1, err = jsonbasics.GetBoolField(data1, TransformKey); err != nil { | ||
return err | ||
} | ||
} | ||
transform2 := true // this is the default value | ||
if data2[TransformKey] != nil { | ||
var err error | ||
if transform2, err = jsonbasics.GetBoolField(data2, TransformKey); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
if transform1 != transform2 { | ||
return errors.New("files with '" + TransformKey + ": true' (default) and '" + | ||
TransformKey + ": false' are not compatible") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// CompatibleVersion checks if 2 files are compatible, by '_format_version'. Version is compatible | ||
// if they are the same major. Missing versions are assumed to be compatible. | ||
// Returns nil if compatible, and error otherwise. | ||
func CompatibleVersion(data1 map[string]interface{}, data2 map[string]interface{}) error { | ||
if data1 == nil { | ||
panic("expected 'data1' to be non-nil") | ||
} | ||
if data2 == nil { | ||
panic("expected 'data2' to be non-nil") | ||
} | ||
|
||
if data1[VersionKey] == nil { | ||
if data2[VersionKey] == nil { | ||
return nil // neither given , so assume compatible | ||
} | ||
// data1 omitted, just validate data2 has a proper version, any version will do | ||
_, _, err := ParseFormatVersion(data2) | ||
return err | ||
} | ||
|
||
// data1 has a version | ||
if data2[VersionKey] == nil { | ||
// data2 omitted, just validate data1 has a proper version, any version will do | ||
_, _, err := ParseFormatVersion(data1) | ||
return err | ||
} | ||
|
||
// both versions given, go parse them | ||
major1, minor1, err1 := ParseFormatVersion(data1) | ||
if err1 != nil { | ||
return err1 | ||
} | ||
major2, minor2, err2 := ParseFormatVersion(data2) | ||
if err2 != nil { | ||
return err2 | ||
} | ||
|
||
if major1 != major2 { | ||
return fmt.Errorf("major versions are incompatible; %d.%d and %d.%d", major1, minor1, major2, minor2) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// CompatibleFile returns nil if the files are compatible. An error otherwise. | ||
// see CompatibleVersion and CompatibleTransform for what compatibility means. | ||
func CompatibleFile(data1 map[string]interface{}, data2 map[string]interface{}) error { | ||
err := CompatibleTransform(data1, data2) | ||
if err != nil { | ||
return fmt.Errorf("files are incompatible; %w", err) | ||
} | ||
err = CompatibleVersion(data1, data2) | ||
if err != nil { | ||
return fmt.Errorf("files are incompatible; %w", err) | ||
} | ||
return nil | ||
} | ||
|
||
// parseFormatVersion parses field `_format_version` and returns major+minor. | ||
// Field must be present, a string, and have an 'x.y' format. Returns an error otherwise. | ||
func ParseFormatVersion(data map[string]interface{}) (int, int, error) { | ||
// get the file version and check it | ||
v, err := jsonbasics.GetStringField(data, VersionKey) | ||
if err != nil { | ||
return 0, 0, errors.New("expected field '." + VersionKey + "' to be a string in 'x.y' format") | ||
} | ||
elem := strings.Split(v, ".") | ||
if len(elem) > 2 { | ||
return 0, 0, errors.New("expected field '." + VersionKey + "' to be a string in 'x.y' format") | ||
} | ||
|
||
majorVersion, err := strconv.Atoi(elem[0]) | ||
if err != nil { | ||
return 0, 0, errors.New("expected field '." + VersionKey + "' to be a string in 'x.y' format") | ||
} | ||
|
||
minorVersion := 0 | ||
if len(elem) > 1 { | ||
minorVersion, err = strconv.Atoi(elem[1]) | ||
if err != nil { | ||
return 0, 0, errors.New("expected field '." + VersionKey + "' to be a string in 'x.y' format") | ||
} | ||
} | ||
|
||
return majorVersion, minorVersion, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
package deckformat_test | ||
|
||
import ( | ||
. "github.com/kong/go-apiops/deckformat" | ||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var _ = Describe("deckformat", func() { | ||
Describe("ParseFormatVersion", func() { | ||
It("parses a version", func() { | ||
data := map[string]interface{}{ | ||
VersionKey: "123.456", | ||
} | ||
|
||
major, minor, err := ParseFormatVersion(data) | ||
Expect(major).To(Equal(123)) | ||
Expect(minor).To(Equal(456)) | ||
Expect(err).To(BeNil()) | ||
}) | ||
|
||
It("returns minor = 0 if omitted", func() { | ||
data := map[string]interface{}{ | ||
VersionKey: "123", | ||
} | ||
|
||
major, minor, err := ParseFormatVersion(data) | ||
Expect(major).To(Equal(123)) | ||
Expect(minor).To(Equal(0)) | ||
Expect(err).To(BeNil()) | ||
}) | ||
|
||
Describe("returns an error if the version", func() { | ||
It("has more than 2 segments", func() { | ||
data := map[string]interface{}{ | ||
VersionKey: "123.456.789", | ||
} | ||
|
||
major, minor, err := ParseFormatVersion(data) | ||
Expect(err).To(MatchError("expected field '._format_version' to be a string in 'x.y' format")) | ||
Expect(major).To(Equal(0)) | ||
Expect(minor).To(Equal(0)) | ||
}) | ||
|
||
It("has a non-numeric major", func() { | ||
data := map[string]interface{}{ | ||
VersionKey: "abc.456", | ||
} | ||
|
||
major, minor, err := ParseFormatVersion(data) | ||
Expect(err).To(MatchError("expected field '._format_version' to be a string in 'x.y' format")) | ||
Expect(major).To(Equal(0)) | ||
Expect(minor).To(Equal(0)) | ||
}) | ||
|
||
It("has a non-numeric minor", func() { | ||
data := map[string]interface{}{ | ||
VersionKey: "123.def", | ||
} | ||
|
||
major, minor, err := ParseFormatVersion(data) | ||
Expect(err).To(MatchError("expected field '._format_version' to be a string in 'x.y' format")) | ||
Expect(major).To(Equal(0)) | ||
Expect(minor).To(Equal(0)) | ||
}) | ||
|
||
It("doesn't exist", func() { | ||
data := map[string]interface{}{} | ||
|
||
major, minor, err := ParseFormatVersion(data) | ||
Expect(err).To(MatchError("expected field '._format_version' to be a string in 'x.y' format")) | ||
Expect(major).To(Equal(0)) | ||
Expect(minor).To(Equal(0)) | ||
}) | ||
|
||
It("doesn't exist, because data is nil", func() { | ||
major, minor, err := ParseFormatVersion(nil) | ||
Expect(err).To(MatchError("expected field '._format_version' to be a string in 'x.y' format")) | ||
Expect(major).To(Equal(0)) | ||
Expect(minor).To(Equal(0)) | ||
}) | ||
}) | ||
}) | ||
|
||
Describe("compatibility", func() { | ||
DescribeTable("CompatibleTransform", | ||
func(transform1 interface{}, transform2 interface{}, expected bool) { | ||
res := CompatibleTransform( | ||
map[string]interface{}{TransformKey: transform1}, | ||
map[string]interface{}{TransformKey: transform2}, | ||
) | ||
if expected { | ||
// compatible, then result is nil | ||
Expect(res).To(BeNil()) | ||
} else { | ||
// not-compatible, then result is an error | ||
Expect(res).Should(HaveOccurred()) | ||
} | ||
}, | ||
// transform1, transform2, expected | ||
Entry("1", true, false, false), | ||
Entry("2", true, true, true), | ||
Entry("3", true, nil, true), | ||
Entry("4", false, false, true), | ||
Entry("5", false, true, false), | ||
Entry("6", false, nil, false), | ||
Entry("7", nil, false, false), | ||
Entry("8", nil, true, true), | ||
Entry("9", nil, nil, true), | ||
) | ||
|
||
DescribeTable("CompatibleVersion", | ||
func(version1 interface{}, version2 interface{}, expected bool) { | ||
res := CompatibleVersion( | ||
map[string]interface{}{VersionKey: version1}, | ||
map[string]interface{}{VersionKey: version2}, | ||
) | ||
if expected { | ||
// compatible, then result is nil | ||
Expect(res).To(BeNil()) | ||
} else { | ||
// not-compatible, then result is an error | ||
Expect(res).Should(HaveOccurred()) | ||
} | ||
}, | ||
// version1, version2, expected | ||
Entry("same major is compatible", "1.1", "1.2", true), | ||
Entry("different major is incompatible", "1.1", "2.1", false), | ||
Entry("omitted version is compatible 1", "1.1", nil, true), | ||
Entry("omitted version is compatible 2", nil, "1.1", true), | ||
Entry("omitted version is compatible 3", nil, nil, true), | ||
Entry("bad version is incompatible 1", "bad", "1.1", false), | ||
Entry("bad version is incompatible 2", "bad", nil, false), | ||
Entry("bad version is incompatible 3", "1.1", "bad", false), | ||
Entry("bad version is incompatible 4", nil, "bad", false), | ||
) | ||
|
||
DescribeTable("CompatibleFile", | ||
func(version1 interface{}, transform1 interface{}, version2 interface{}, transform2 interface{}, expected bool) { | ||
res := CompatibleFile( | ||
map[string]interface{}{ | ||
VersionKey: version1, | ||
TransformKey: transform1, | ||
}, | ||
map[string]interface{}{ | ||
VersionKey: version2, | ||
TransformKey: transform2, | ||
}, | ||
) | ||
if expected { | ||
// compatible, then result is nil | ||
Expect(res).To(BeNil()) | ||
} else { | ||
// not-compatible, then result is an error | ||
Expect(res).Should(HaveOccurred()) | ||
} | ||
}, | ||
// version1, version2, expected | ||
Entry("1", "1.1", true, "1.2", true, true), | ||
Entry("2", "1.1", true, "1.2", false, false), | ||
Entry("3", "1.1", true, "2.1", true, false), | ||
) | ||
}) | ||
}) |
Oops, something went wrong.