From 98a35831f0cf1113e84c48beba0054a42e6d07a1 Mon Sep 17 00:00:00 2001 From: Ray Miller Date: Wed, 10 May 2023 16:57:48 +0100 Subject: [PATCH] Bugfix parsing of quoted strings, better error reporting for config errors. --- main.go | 17 +++++----- main_test.go | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 main_test.go diff --git a/main.go b/main.go index 45ea149..6d0d00a 100644 --- a/main.go +++ b/main.go @@ -235,11 +235,15 @@ func parseConfig(f io.Reader) (config, error) { } k, v, ok := strings.Cut(t, "=") if !ok { - return conf, fmt.Errorf("invalid configuration: %s", t) + return conf, fmt.Errorf("error parsing %s: invalid syntax", t) } k, v = strings.TrimSpace(k), strings.TrimSpace(v) if len(v) >= 2 && strings.HasPrefix(v, "\"") && strings.HasSuffix(v, "\"") { - v = strings.Trim(v, "\"") + unquotedV, err := strconv.Unquote(v) + if err != nil { + return conf, fmt.Errorf("error parsing %s: invalid quoted string", t) + } + v = unquotedV } switch strings.ToUpper(k) { case "VERSION_PREFIX": @@ -247,17 +251,14 @@ func parseConfig(f io.Reader) (config, error) { case "GIT_SIGN": b, err := strconv.ParseBool(v) if err != nil { - return conf, fmt.Errorf("error parsing GIT_SIGN %q: %v", v, err) + return conf, fmt.Errorf("error parsing %s: invalid boolean value", t) } conf.sign = b default: - return conf, fmt.Errorf("unrecognized configuration variable: %s", k) + return conf, fmt.Errorf("error parsing %s: unrecognized variable", t) } } - if err := s.Err(); err != nil { - return conf, err - } - return conf, nil + return conf, s.Err() } func createTag(tagName string, sign bool) error { diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..841eb3e --- /dev/null +++ b/main_test.go @@ -0,0 +1,87 @@ +package main + +import ( + "strconv" + "strings" + "testing" +) + +func TestParseConfig(t *testing.T) { + + testCases := []struct { + input string + expect config + expectErr string + }{ + { + input: "VERSION_PREFIX=v\n", + expect: config{versionPrefix: "v"}, + }, + { + input: "GIT_SIGN=1\n", + expect: config{sign: true}, + }, + { + input: "VERSION_PREFIX=v\nGIT_SIGN=t\n", + expect: config{versionPrefix: "v", sign: true}, + }, + { + input: "version_prefix=v\ngit_sign=t\n", + expect: config{versionPrefix: "v", sign: true}, + }, + { + input: "VERSION_PREFIX=v\nGIT_SIGN=false\n", + expect: config{versionPrefix: "v", sign: false}, + }, + { + input: "VERSION_PREFIX=\"version/\"\nGIT_SIGN=f\n", + expect: config{versionPrefix: "version/", sign: false}, + }, + { + input: "VERSION_PREFIX=\"foo\\\"bar\"\n", + expect: config{versionPrefix: "foo\"bar"}, + }, + { + input: "foo\n", + expectErr: "error parsing foo: invalid syntax", + }, + { + input: "bad_key=v\n", + expectErr: "error parsing bad_key=v: unrecognized variable", + }, + { + input: "GIT_SIGN=wibble\n", + expectErr: "error parsing GIT_SIGN=wibble: invalid boolean value", + }, + { + input: "VERSION_PREFIX=\"foo\\z\"\n", + expectErr: "error parsing VERSION_PREFIX=\"foo\\z\": invalid quoted string", + }, + } + + for i, tc := range testCases { + t.Run(strconv.Itoa(i), func(t *testing.T) { + res, err := parseConfig(strings.NewReader(tc.input)) + if tc.expectErr != "" { + if err == nil { + t.Error("expected error not returned") + return + } + if err.Error() != tc.expectErr { + t.Errorf("expected error %q, got %q", tc.expectErr, err.Error()) + } + } else { + if err != nil { + t.Errorf("got unexpected error: %v", err) + } + if res.versionPrefix != tc.expect.versionPrefix { + t.Errorf("got versionPrefix %s, expected %s", res.versionPrefix, tc.expect.versionPrefix) + } + if res.sign != tc.expect.sign { + t.Errorf("got sign %t, expected %t", res.sign, tc.expect.sign) + } + } + }) + } + +}