Skip to content
Open
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
63 changes: 63 additions & 0 deletions v2/internal/pkg/parser/parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//nolint:ireturn // generic T should be fine to return here
package parser

import (
"encoding/json"
"fmt"
"io"
"os"

"sigs.k8s.io/yaml"
)

// ParseJsonFile reads json `file` and parses it as type T
func ParseJsonFile[T any](file string) (T, error) {
var t T
data, err := os.ReadFile(file)
if err != nil {
return t, fmt.Errorf("read file: %w", err)
}
if err := json.Unmarshal(data, &t); err != nil {
return t, fmt.Errorf("parse file: %w", err)
}
return t, nil
}

// ParseJsonReader parses json from a stream into a type T
func ParseJsonReader[T any](r io.Reader) (T, error) {
var t T
data, err := io.ReadAll(r)
if err != nil {
return t, fmt.Errorf("read stream: %w", err)
}
if err := json.Unmarshal(data, &t); err != nil {
return t, fmt.Errorf("parse stream: %w", err)
}
return t, nil
}

// ParseYamlFile reads yaml `file` and parses it as type T
func ParseYamlFile[T any](file string) (T, error) {
var t T
data, err := os.ReadFile(file)
if err != nil {
return t, fmt.Errorf("read file: %w", err)
}
if err := yaml.Unmarshal(data, &t); err != nil {
return t, fmt.Errorf("parse file: %w", err)
}
return t, nil
}

// ParseYamlReader parses yaml from a stream into a type T
func ParseYamlReader[T any](r io.Reader) (T, error) {
var t T
data, err := io.ReadAll(r)
if err != nil {
return t, fmt.Errorf("read stream: %w", err)
}
if err := yaml.Unmarshal(data, &t); err != nil {
return t, fmt.Errorf("parse stream: %w", err)
}
return t, nil
}
59 changes: 59 additions & 0 deletions v2/internal/pkg/parser/parse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package parser

import (
"os"
"path"
"testing"

"github.com/stretchr/testify/assert"
)

func TestParseJsonFromFile(t *testing.T) {
type custom struct{ field string } //nolint:unused // just a dummy type
// We don't really need to test this functionality.
// These tests exist just to sanity check the error messages.
t.Run("Testing ParseJsonFile should fail", func(t *testing.T) {
t.Run("with invalid file", func(t *testing.T) {
res, err := ParseJsonFile[custom]("invalid-file")
assert.Empty(t, res)
assert.Error(t, err)
assert.Regexp(t, "read file: open .*: no such file or directory", err)
})

t.Run("with malformed json", func(t *testing.T) {
filePath := path.Join(t.TempDir(), "index.json")
err := os.WriteFile(filePath, []byte("invalid"), 0o644) //nolint:gosec // temp file
assert.NoError(t, err, "should create invalid index.json")

res, err := ParseJsonFile[custom](filePath)
assert.Empty(t, res)
assert.Error(t, err)
assert.Regexp(t, "parse file: .*", err)
})
})
}

func TestParseYamlFromFile(t *testing.T) {
type custom struct{ field string } //nolint:unused // just a dummy type
// We don't really need to test this functionality.
// These tests exist just to sanity check the error messages.
t.Run("Testing ParseYamlFile should fail", func(t *testing.T) {
t.Run("with invalid file", func(t *testing.T) {
res, err := ParseYamlFile[custom]("invalid-file")
assert.Empty(t, res)
assert.Error(t, err)
assert.Regexp(t, "read file: open .*: no such file or directory", err)
})

t.Run("with malformed yaml", func(t *testing.T) {
filePath := path.Join(t.TempDir(), "index.yaml")
err := os.WriteFile(filePath, []byte("invalid\nyaml"), 0o644) //nolint:gosec // temp file
assert.NoError(t, err, "should create invalid index.yaml")

res, err := ParseYamlFile[custom](filePath)
assert.Empty(t, res)
assert.Error(t, err)
assert.Regexp(t, "parse file: .*", err)
})
})
}