From be4c9c0e8c5c8d9b5eb02826d2fd1227c8502d62 Mon Sep 17 00:00:00 2001 From: Rohan Verma Date: Wed, 6 Mar 2024 23:43:58 +0530 Subject: [PATCH] tests: add unit tests for parser errors - Declares errors and wraps them for error checking by clients - Adds two unit tests for - terminated quote error - unexpected char --- godotenv_test.go | 42 ++++++++++++++++++++++++++++++++++-------- parser.go | 13 ++++++++++--- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/godotenv_test.go b/godotenv_test.go index c6d7e54..bfa7f96 100644 --- a/godotenv_test.go +++ b/godotenv_test.go @@ -2,6 +2,7 @@ package godotenv import ( "bytes" + "errors" "fmt" "os" "reflect" @@ -582,42 +583,42 @@ func TestWhitespace(t *testing.T) { }{ "Leading whitespace": { input: " A=a\n", - key: "A", + key: "A", value: "a", }, "Leading tab": { input: "\tA=a\n", - key: "A", + key: "A", value: "a", }, "Leading mixed whitespace": { input: " \t \t\n\t \t A=a\n", - key: "A", + key: "A", value: "a", }, "Leading whitespace before export": { input: " \t\t export A=a\n", - key: "A", + key: "A", value: "a", }, "Trailing whitespace": { input: "A=a \t \t\n", - key: "A", + key: "A", value: "a", }, "Trailing whitespace with export": { input: "export A=a\t \t \n", - key: "A", + key: "A", value: "a", }, "No EOL": { input: "A=a", - key: "A", + key: "A", value: "a", }, "Trailing whitespace with no EOL": { input: "A=a ", - key: "A", + key: "A", value: "a", }, } @@ -634,3 +635,28 @@ func TestWhitespace(t *testing.T) { }) } } + +func TestParserErrors(t *testing.T) { + cases := map[string]struct { + input string + err error + }{ + "Invalid char": { + input: "foo-1=bar", + err: ErrUnexpectedChar, + }, + "UnterminatedQuote": { + input: "foo=\"bar", + err: ErrUnterminatedQuote, + }, + } + + for n, c := range cases { + t.Run(n, func(t *testing.T) { + v, err := Unmarshal(c.input) + if !errors.Is(err, c.err) { + t.Errorf("Input: %q Expected:\t %q\nGot:\t %q Val: %v", c.input, c.err, err, v) + } + }) + } +} diff --git a/parser.go b/parser.go index cc709af..369e90c 100644 --- a/parser.go +++ b/parser.go @@ -17,6 +17,12 @@ const ( exportPrefix = "export" ) +var ( + ErrZeroLengthString = errors.New("zero length string") + ErrUnexpectedChar = errors.New("unexpected character") + ErrUnterminatedQuote = errors.New("unterminated quoted value") +) + func parseBytes(src []byte, out map[string]string) error { src = bytes.Replace(src, []byte("\r\n"), []byte("\n"), -1) cutset := src @@ -101,13 +107,14 @@ loop: } return "", nil, fmt.Errorf( - `unexpected character %q in variable name near %q`, + `%w %q in variable name near %q`, + ErrUnexpectedChar, string(char), string(src)) } } if len(src) == 0 { - return "", nil, errors.New("zero length string") + return "", nil, ErrZeroLengthString } // trim whitespace @@ -186,7 +193,7 @@ func extractVarValue(src []byte, vars map[string]string) (value string, rest []b valEndIndex = len(src) } - return "", nil, fmt.Errorf("unterminated quoted value %s", src[:valEndIndex]) + return "", nil, fmt.Errorf("%w %s", ErrUnterminatedQuote, src[:valEndIndex]) } func expandEscapes(str string) string {