Skip to content

Commit

Permalink
Fix unmarshaling empty strings (#7)
Browse files Browse the repository at this point in the history
Signed-off-by: Kimmo Lehto <[email protected]>
  • Loading branch information
kke authored Sep 5, 2023
1 parent e2b282d commit acbe5a4
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 3 deletions.
29 changes: 28 additions & 1 deletion version.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@ func pair(a, b *Version) Collection {

// String returns a v-prefixed string representation of the k0s version
func (v *Version) String() string {
return fmt.Sprintf("v%s", v.Version.String())
if v == nil {
return ""
}
plain := strings.TrimPrefix(v.Version.String(), "v")
if plain == "" {
return ""
}
return fmt.Sprintf("v%s", plain)
}

func (v *Version) urlString() string {
Expand Down Expand Up @@ -112,11 +119,19 @@ func (v *Version) Compare(b *Version) int {

// MarshalJSON implements the json.Marshaler interface.
func (v *Version) MarshalJSON() ([]byte, error) {
if v == nil {
return []byte("null"), nil
}

return []byte(fmt.Sprintf("\"%s\"", v.String())), nil
}

// MarshalYAML implements the yaml.Marshaler interface.
func (v *Version) MarshalYAML() (interface{}, error) {
if v == nil {
return nil, nil
}

return v.String(), nil
}

Expand All @@ -125,6 +140,9 @@ func (v *Version) unmarshal(f func(interface{}) error) error {
if err := f(&s); err != nil {
return fmt.Errorf("failed to decode input: %w", err)
}
if s == "" {
return nil
}
newV, err := NewVersion(s)
if err != nil {
return fmt.Errorf("failed to unmarshal version: %w", err)
Expand All @@ -141,12 +159,21 @@ func (v *Version) UnmarshalYAML(f func(interface{}) error) error {
// UnmarshalJSON implements the json.Unmarshaler interface.
func (v *Version) UnmarshalJSON(b []byte) error {
s := strings.TrimSpace(strings.Trim(string(b), "\""))
if s == "" || s == "null" {
// go doesn't allow to set nil to a non-pointer struct field, so the result
// is going to be an empty struct
return nil
}
return v.unmarshal(func(i interface{}) error {
*(i.(*string)) = s
return nil
})
}

func (v *Version) IsZero() bool {
return v == nil || v.String() == ""
}

// Satisfies returns true if the version satisfies the supplied constraint
func (v *Version) Satisfies(constraint Constraints) bool {
return constraint.Check(v)
Expand Down
34 changes: 32 additions & 2 deletions version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,25 @@ func TestMarshalling(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, "v1.0.0+k0s.0", yamlData)
})

t.Run("JSON with nil", func(t *testing.T) {
jsonData, err := json.Marshal(nil)
assert.NoError(t, err)
assert.Equal(t, `null`, string(jsonData))
})

t.Run("YAML", func(t *testing.T) {
var nilVersion *Version
yamlData, err := nilVersion.MarshalYAML()
assert.NoError(t, err)
assert.Nil(t, yamlData)
})
}

func TestUnmarshalling(t *testing.T) {
t.Run("JSON", func(t *testing.T) {
var v Version
err := json.Unmarshal([]byte(`"v1.0.0+k0s.1"`), &v)
v := &Version{}
err := json.Unmarshal([]byte(`"v1.0.0+k0s.1"`), v)
assert.NoError(t, err)
assert.Equal(t, "v1.0.0+k0s.1", v.String())
})
Expand All @@ -95,6 +108,23 @@ func TestUnmarshalling(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, "v1.0.0+k0s.1", v.String())
})

t.Run("JSON with null", func(t *testing.T) {
v := &Version{}
err := json.Unmarshal([]byte(`null`), v)
assert.NoError(t, err)
assert.True(t, v.IsZero())
})

t.Run("YAML with empty", func(t *testing.T) {
v := &Version{}
err := v.UnmarshalYAML(func(i interface{}) error {
*(i.(*string)) = ""
return nil
})
assert.NoError(t, err)
assert.Nil(t, nil, v)
})
}

func TestFailingUnmarshalling(t *testing.T) {
Expand Down

0 comments on commit acbe5a4

Please sign in to comment.