refactor!: sizeable changes across the board

This commit is contained in:
2024-03-19 03:54:31 +00:00
parent a1b1ef82ad
commit 7632b1119c
22 changed files with 620 additions and 733 deletions

View File

@@ -35,7 +35,7 @@ type mockRenderer struct {
err error
}
var _ render.Renderer = (*mockRenderer)(nil)
var _ render.FormatRenderer = (*mockRenderer)(nil)
func (m *mockRenderer) Render(w io.Writer, _ any) error {
_, err := w.Write([]byte(m.output))
@@ -59,23 +59,8 @@ func TestDefaultYAML(t *testing.T) {
assert.Equal(t, &render.YAML{Indent: 2}, render.DefaultYAML)
}
func TestDefaultWriterTo(t *testing.T) {
assert.Equal(t, &render.WriterTo{}, render.DefaultWriterTo)
}
func TestDefaultStringer(t *testing.T) {
assert.Equal(t, &render.Stringer{}, render.DefaultStringer)
}
func TestDefaultText(t *testing.T) {
want := &render.MultiRenderer{
Renderers: []render.Renderer{
&render.Stringer{},
&render.WriterTo{},
},
}
assert.Equal(t, want, render.DefaultText)
assert.Equal(t, &render.Text{}, render.DefaultText)
}
func TestDefaultBinary(t *testing.T) {
@@ -83,408 +68,253 @@ func TestDefaultBinary(t *testing.T) {
}
func TestDefaultRenderer(t *testing.T) {
want := &render.FormatRenderer{
Renderers: map[string]render.Renderer{
"bin": render.DefaultBinary,
"binary": render.DefaultBinary,
"json": render.DefaultJSON,
"plain": render.DefaultText,
"text": render.DefaultText,
"txt": render.DefaultText,
"xml": render.DefaultXML,
"yaml": render.DefaultYAML,
"yml": render.DefaultYAML,
want := &render.Renderer{
Formats: map[string]render.FormatRenderer{
"json": render.DefaultJSON,
"text": render.DefaultText,
"yaml": render.DefaultYAML,
},
}
assert.Equal(t, want, render.DefaultRenderer)
}
type renderFormatTestCase struct {
name string
writeErr error
format string
value any
want string
wantErr string
wantErrIs []error
wantPanic string
}
// "binary" format.
var binaryFormattestCases = []renderFormatTestCase{
{
name: "binary format with binary marshaler",
format: "binary",
value: &mockBinaryMarshaler{data: []byte("test string")},
want: "test string",
},
{
name: "binary format without binary marshaler",
format: "binary",
value: struct{}{},
wantErr: "render: unsupported format: binary",
wantErrIs: []error{render.Err, render.ErrUnsupportedFormat},
},
{
name: "binary format with error marshaling",
format: "binary",
value: &mockBinaryMarshaler{
data: []byte("test string"),
err: errors.New("marshal error!!1"),
},
wantErr: "render: failed: marshal error!!1",
wantErrIs: []error{render.Err, render.ErrFailed},
},
{
name: "binary format with error writing to writer",
format: "binary",
writeErr: errors.New("write error!!1"),
value: &mockBinaryMarshaler{data: []byte("test string")},
wantErr: "render: failed: write error!!1",
wantErrIs: []error{render.Err, render.ErrFailed},
},
{
name: "binary format with invalid type",
format: "binary",
value: make(chan int),
wantErr: "render: unsupported format: binary",
wantErrIs: []error{render.Err, render.ErrUnsupportedFormat},
},
}
// "json" format.
var jsonFormatTestCases = []renderFormatTestCase{
{
name: "json format",
format: "json",
value: map[string]int{"age": 30},
want: "{\n \"age\": 30\n}\n",
},
{
name: "json format with json marshaler",
format: "json",
value: &mockJSONMarshaler{data: []byte(`{"age":30}`)},
want: "{\n \"age\": 30\n}\n",
},
{
name: "json format with error from json marshaler",
format: "json",
value: &mockJSONMarshaler{err: errors.New("marshal error!!1")},
wantErrIs: []error{render.Err},
},
{
name: "json format with error writing to writer",
format: "json",
writeErr: errors.New("write error!!1"),
value: map[string]int{"age": 30},
wantErr: "render: failed: write error!!1",
wantErrIs: []error{render.Err, render.ErrFailed},
},
{
name: "json format with invalid type",
format: "json",
value: make(chan int),
wantErr: "render: failed: json: unsupported type: chan int",
wantErrIs: []error{render.Err, render.ErrFailed},
},
}
// "text" format.
var textFormatTestCases = []renderFormatTestCase{
{
name: "text format with fmt.Stringer",
format: "text",
value: &mockStringer{value: "test string"},
want: "test string",
},
{
name: "text format with io.WriterTo",
format: "text",
value: &mockWriterTo{value: "test string"},
want: "test string",
},
{
name: "text format without fmt.Stringer or io.WriterTo",
format: "text",
value: struct{}{},
wantErr: "render: unsupported format: text",
wantErrIs: []error{render.Err, render.ErrUnsupportedFormat},
},
{
name: "text format with error writing to writer",
format: "text",
writeErr: errors.New("write error!!1"),
value: &mockStringer{value: "test string"},
wantErr: "render: failed: write error!!1",
wantErrIs: []error{render.Err, render.ErrFailed},
},
{
name: "text format with error from io.WriterTo",
format: "text",
value: &mockWriterTo{
value: "test string",
err: errors.New("WriteTo error!!1"),
},
wantErr: "render: failed: WriteTo error!!1",
wantErrIs: []error{render.Err, render.ErrFailed},
},
{
name: "text format with invalid type",
format: "text",
value: make(chan int),
wantErr: "render: unsupported format: text",
wantErrIs: []error{render.Err, render.ErrUnsupportedFormat},
},
}
// "xml" format.
var xmlFormatTestCases = []renderFormatTestCase{
{
name: "xml format",
format: "xml",
value: struct {
XMLName xml.Name `xml:"user"`
Age int `xml:"age"`
}{Age: 30},
want: "<user>\n <age>30</age>\n</user>",
},
{
name: "xml format with xml.Marshaler",
format: "xml",
value: &mockXMLMarshaler{elm: "test string"},
want: "<mockXMLMarshaler>test string</mockXMLMarshaler>",
},
{
name: "xml format with error from xml.Marshaler",
format: "xml",
value: &mockXMLMarshaler{err: errors.New("marshal error!!1")},
wantErr: "render: failed: marshal error!!1",
wantErrIs: []error{render.Err, render.ErrFailed},
},
{
name: "xml format with error writing to writer",
format: "xml",
writeErr: errors.New("write error!!1"),
value: struct {
XMLName xml.Name `xml:"user"`
Age int `xml:"age"`
}{Age: 30},
wantErr: "render: failed: write error!!1",
wantErrIs: []error{render.Err, render.ErrFailed},
},
{
name: "xml format with invalid value",
format: "xml",
value: make(chan int),
wantErr: "render: failed: xml: unsupported type: chan int",
wantErrIs: []error{render.Err, render.ErrFailed},
},
}
// "yaml" format.
var yamlFormatTestCases = []renderFormatTestCase{
{
name: "yaml format",
format: "yaml",
value: map[string]int{"age": 30},
want: "age: 30\n",
},
{
name: "yaml format with nested structure",
format: "yaml",
value: map[string]any{
"user": map[string]any{
"age": 30,
"name": "John Doe",
},
},
want: "user:\n age: 30\n name: John Doe\n",
},
{
name: "yaml format with yaml.Marshaler",
format: "yaml",
value: &mockYAMLMarshaler{val: map[string]int{"age": 30}},
want: "age: 30\n",
},
{
name: "yaml format with error from yaml.Marshaler",
format: "yaml",
value: &mockYAMLMarshaler{err: errors.New("mock error")},
wantErr: "render: failed: mock error",
wantErrIs: []error{render.Err, render.ErrFailed},
},
{
name: "yaml format with error writing to writer",
format: "yaml",
writeErr: errors.New("write error!!1"),
value: map[string]int{"age": 30},
wantErr: "render: failed: yaml: write error: write error!!1",
wantErrIs: []error{render.Err, render.ErrFailed},
},
{
name: "yaml format with invalid type",
format: "yaml",
value: make(chan int),
wantPanic: "cannot marshal type: chan int",
},
}
func TestRender(t *testing.T) {
tests := []struct {
name string
writeErr error
format string
value any
want string
wantErr string
wantErrIs []error
wantPanic string
}{
// "bin" format.
{
name: "bin format with binary marshaler",
format: "bin",
value: &mockBinaryMarshaler{data: []byte("test string")},
want: "test string",
},
{
name: "bin format without binary marshaler",
format: "bin",
value: struct{}{},
wantErrIs: []error{render.Err, render.ErrCannotRender},
},
{
name: "bin format with error marshaling",
format: "bin",
value: &mockBinaryMarshaler{
data: []byte("test string"),
err: errors.New("marshal error!!1"),
},
wantErr: "render: marshal error!!1",
wantErrIs: []error{render.Err},
},
{
name: "bin format with error writing to writer",
format: "bin",
writeErr: errors.New("write error!!1"),
value: &mockBinaryMarshaler{data: []byte("test string")},
wantErr: "render: write error!!1",
wantErrIs: []error{render.Err},
},
{
name: "bin format with invalid type",
format: "bin",
value: make(chan int),
wantErr: "render: cannot render",
wantErrIs: []error{render.Err, render.ErrCannotRender},
},
// "binary" format.
{
name: "binary format with binary marshaler",
format: "binary",
value: &mockBinaryMarshaler{data: []byte("test string")},
want: "test string",
},
{
name: "binary format without binary marshaler",
format: "binary",
value: struct{}{},
wantErrIs: []error{render.Err, render.ErrCannotRender},
},
{
name: "binary format with error marshaling",
format: "binary",
value: &mockBinaryMarshaler{
data: []byte("test string"),
err: errors.New("marshal error!!1"),
},
wantErr: "render: marshal error!!1",
wantErrIs: []error{render.Err},
},
{
name: "binary format with error writing to writer",
format: "binary",
writeErr: errors.New("write error!!1"),
value: &mockBinaryMarshaler{data: []byte("test string")},
wantErr: "render: write error!!1",
wantErrIs: []error{render.Err},
},
{
name: "binary format with invalid type",
format: "binary",
value: make(chan int),
wantErr: "render: cannot render",
wantErrIs: []error{render.Err, render.ErrCannotRender},
},
// "json" format.
{
name: "json format",
format: "json",
value: map[string]int{"age": 30},
want: "{\n \"age\": 30\n}\n",
},
{
name: "json format with json marshaler",
format: "json",
value: &mockJSONMarshaler{data: []byte(`{"age":30}`)},
want: "{\n \"age\": 30\n}\n",
},
{
name: "json format with error from json marshaler",
format: "json",
value: &mockJSONMarshaler{err: errors.New("marshal error!!1")},
wantErrIs: []error{render.Err},
},
{
name: "json format with error writing to writer",
format: "json",
writeErr: errors.New("write error!!1"),
value: map[string]int{"age": 30},
wantErr: "render: write error!!1",
wantErrIs: []error{render.Err},
},
{
name: "json format with invalid type",
format: "json",
value: make(chan int),
wantErr: "render: json: unsupported type: chan int",
wantErrIs: []error{render.Err},
},
// "plain" format.
{
name: "plain format with fmt.Stringer",
format: "plain",
value: &mockStringer{value: "test string"},
want: "test string",
},
{
name: "plain format with io.WriterTo",
format: "plain",
value: &mockWriterTo{value: "test string"},
want: "test string",
},
{
name: "plain format without fmt.Stringer or io.WriterTo",
format: "plain",
value: struct{}{},
wantErrIs: []error{render.Err, render.ErrCannotRender},
},
{
name: "plain format with error writing to writer",
format: "plain",
writeErr: errors.New("write error!!1"),
value: &mockStringer{value: "test string"},
wantErr: "render: write error!!1",
wantErrIs: []error{render.Err},
},
{
name: "plain format with error from io.WriterTo",
format: "plain",
value: &mockWriterTo{
value: "test string",
err: errors.New("WriteTo error!!1"),
},
wantErr: "render: WriteTo error!!1",
wantErrIs: []error{render.Err},
},
{
name: "plain format with invalid type",
format: "plain",
value: make(chan int),
wantErr: "render: cannot render",
wantErrIs: []error{render.Err, render.ErrCannotRender},
},
// "text" format.
{
name: "text format with fmt.Stringer",
format: "text",
value: &mockStringer{value: "test string"},
want: "test string",
},
{
name: "text format with io.WriterTo",
format: "text",
value: &mockWriterTo{value: "test string"},
want: "test string",
},
{
name: "text format without fmt.Stringer or io.WriterTo",
format: "text",
value: struct{}{},
wantErrIs: []error{render.Err, render.ErrCannotRender},
},
{
name: "text format with error writing to writer",
format: "text",
writeErr: errors.New("write error!!1"),
value: &mockStringer{value: "test string"},
wantErr: "render: write error!!1",
wantErrIs: []error{render.Err},
},
{
name: "text format with error from io.WriterTo",
format: "text",
value: &mockWriterTo{
value: "test string",
err: errors.New("WriteTo error!!1"),
},
wantErr: "render: WriteTo error!!1",
wantErrIs: []error{render.Err},
},
{
name: "text format with invalid type",
format: "text",
value: make(chan int),
wantErr: "render: cannot render",
wantErrIs: []error{render.Err, render.ErrCannotRender},
},
// "txt" format.
{
name: "txt format with fmt.Stringer",
format: "txt",
value: &mockStringer{value: "test string"},
want: "test string",
},
{
name: "txt format with io.WriterTo",
format: "txt",
value: &mockWriterTo{value: "test string"},
want: "test string",
},
{
name: "txt format without fmt.Stringer or io.WriterTo",
format: "txt",
value: struct{}{},
wantErrIs: []error{render.Err, render.ErrCannotRender},
},
{
name: "txt format with error writing to writer",
format: "txt",
writeErr: errors.New("write error!!1"),
value: &mockStringer{value: "test string"},
wantErr: "render: write error!!1",
wantErrIs: []error{render.Err},
},
{
name: "txt format with error from io.WriterTo",
format: "txt",
value: &mockWriterTo{
value: "test string",
err: errors.New("WriteTo error!!1"),
},
wantErr: "render: WriteTo error!!1",
wantErrIs: []error{render.Err},
},
{
name: "txt format with invalid type",
format: "txt",
value: make(chan int),
wantErr: "render: cannot render",
wantErrIs: []error{render.Err, render.ErrCannotRender},
},
// "xml" format.
{
name: "xml format",
format: "xml",
value: struct {
XMLName xml.Name `xml:"user"`
Age int `xml:"age"`
}{Age: 30},
want: "<user>\n <age>30</age>\n</user>",
},
{
name: "xml format with xml.Marshaler",
format: "xml",
value: &mockXMLMarshaler{elm: "test string"},
want: "<mockXMLMarshaler>test string</mockXMLMarshaler>",
},
{
name: "xml format with error from xml.Marshaler",
format: "xml",
value: &mockXMLMarshaler{err: errors.New("marshal error!!1")},
wantErr: "render: marshal error!!1",
wantErrIs: []error{render.Err},
},
{
name: "xml format with error writing to writer",
format: "xml",
writeErr: errors.New("write error!!1"),
value: struct {
XMLName xml.Name `xml:"user"`
Age int `xml:"age"`
}{Age: 30},
wantErr: "render: write error!!1",
wantErrIs: []error{render.Err},
},
{
name: "xml format with invalid value",
format: "xml",
value: make(chan int),
wantErr: "render: xml: unsupported type: chan int",
wantErrIs: []error{render.Err},
},
// "yaml" format.
{
name: "yaml format",
format: "yaml",
value: map[string]int{"age": 30},
want: "age: 30\n",
},
{
name: "yaml format with nested structure",
format: "yaml",
value: map[string]any{
"user": map[string]any{
"age": 30,
"name": "John Doe",
},
},
want: "user:\n age: 30\n name: John Doe\n",
},
{
name: "yaml format with yaml.Marshaler",
format: "yaml",
value: &mockYAMLMarshaler{val: map[string]int{"age": 30}},
want: "age: 30\n",
},
{
name: "yaml format with error from yaml.Marshaler",
format: "yaml",
value: &mockYAMLMarshaler{err: errors.New("mock error")},
wantErr: "render: mock error",
wantErrIs: []error{render.Err},
},
{
name: "yaml format with error writing to writer",
format: "yaml",
writeErr: errors.New("write error!!1"),
value: map[string]int{"age": 30},
wantErr: "render: yaml: write error: write error!!1",
wantErrIs: []error{render.Err},
},
{
name: "yaml format with invalid type",
format: "yaml",
value: make(chan int),
wantPanic: "cannot marshal type: chan int",
},
// "yml" format.
{
name: "yml format",
format: "yml",
value: map[string]int{"age": 30},
want: "age: 30\n",
},
{
name: "yml format with nested structure",
format: "yml",
value: map[string]any{
"user": map[string]any{
"age": 30,
"name": "John Doe",
},
},
want: "user:\n age: 30\n name: John Doe\n",
},
{
name: "yml format with yaml.Marshaler",
format: "yml",
value: &mockYAMLMarshaler{val: map[string]int{"age": 30}},
want: "age: 30\n",
},
{
name: "yml format with error from yaml.Marshaler",
format: "yml",
value: &mockYAMLMarshaler{err: errors.New("mock error")},
wantErr: "render: mock error",
wantErrIs: []error{render.Err},
},
{
name: "yml format with error writing to writer",
format: "yml",
writeErr: errors.New("write error!!1"),
value: map[string]int{"age": 30},
wantErr: "render: yaml: write error: write error!!1",
wantErrIs: []error{render.Err},
},
{
name: "yml format with invalid type",
format: "yml",
value: make(chan int),
wantPanic: "cannot marshal type: chan int",
},
}
tests := []renderFormatTestCase{}
tests = append(tests, jsonFormatTestCases...)
tests = append(tests, textFormatTestCases...)
tests = append(tests, yamlFormatTestCases...)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
w := &mockWriter{WriteErr: tt.writeErr}