From f16508c69728ef0d92897622bc29bed754fd73ae Mon Sep 17 00:00:00 2001 From: Thomas Pelletier Date: Thu, 7 Apr 2022 20:29:01 -0400 Subject: [PATCH] tools: display error context when it exists For example when failing to decode toml, display the context around the error and the location of the problem. --- internal/cli/cli.go | 14 +++++++++++++- internal/cli/cli_test.go | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/internal/cli/cli.go b/internal/cli/cli.go index ea945780..4d50800e 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -2,11 +2,14 @@ package cli import ( "bytes" + "errors" "flag" "fmt" "io" "io/ioutil" "os" + + "github.com/pelletier/go-toml/v2" ) type ConvertFn func(r io.Reader, w io.Writer) error @@ -28,7 +31,16 @@ func (p *Program) Execute() { func (p *Program) main(files []string, input io.Reader, output, error io.Writer) int { err := p.run(files, input, output) if err != nil { - fmt.Fprintln(error, err.Error()) + + var derr *toml.DecodeError + if errors.As(err, &derr) { + fmt.Fprintln(error, derr.String()) + row, col := derr.Position() + fmt.Fprintln(error, "error occurred at row", row, "column", col) + } else { + fmt.Fprintln(error, err.Error()) + } + return -1 } return 0 diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go index 76247365..429fa730 100644 --- a/internal/cli/cli_test.go +++ b/internal/cli/cli_test.go @@ -10,6 +10,7 @@ import ( "strings" "testing" + "github.com/pelletier/go-toml/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -47,6 +48,21 @@ func TestProcessMainStdinErr(t *testing.T) { assert.NotEmpty(t, stderr.String()) } +func TestProcessMainStdinDecodeErr(t *testing.T) { + stdout := new(bytes.Buffer) + stderr := new(bytes.Buffer) + input := strings.NewReader("this is the input") + + exit := processMain([]string{}, input, stdout, stderr, func(r io.Reader, w io.Writer) error { + var v interface{} + return toml.Unmarshal([]byte(`qwe = 001`), &v) + }) + + assert.Equal(t, -1, exit) + assert.Empty(t, stdout.String()) + assert.Contains(t, stderr.String(), "error occurred at") +} + func TestProcessMainFileExists(t *testing.T) { tmpfile, err := ioutil.TempFile("", "example") require.NoError(t, err)