From 2190485745fb270465fabf6af364bcb7dee3b61a Mon Sep 17 00:00:00 2001 From: Steven Sklar Date: Fri, 12 Apr 2024 07:56:26 +0200 Subject: [PATCH] fix(config): enables optional trailing semicolon in config string (#32) --- conf_parse.go | 6 +++++- conf_test.go | 42 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/conf_parse.go b/conf_parse.go index c7c0bae..d3f46dd 100644 --- a/conf_parse.go +++ b/conf_parse.go @@ -186,7 +186,7 @@ func parseConfigStr(conf string) (configData, error) { } if !strings.HasSuffix(conf, ";") { - return result, NewInvalidConfigStrError("trailing semicolon ';' required") + conf += ";" } keyValueStr := []rune(conf) @@ -216,6 +216,10 @@ func parseConfigStr(conf string) (configData, error) { continue } + if value.Len() == 0 { + return result, NewInvalidConfigStrError("empty value for key %q", key) + } + result.KeyValuePairs[key.String()] = value.String() key.Reset() diff --git a/conf_test.go b/conf_test.go index d6cd1be..c2f5ea0 100644 --- a/conf_test.go +++ b/conf_test.go @@ -213,6 +213,16 @@ func TestParserHappyCases(t *testing.T) { }, }, }, + { + name: "no trailing semicolon", + config: fmt.Sprintf("http::addr=%s", addr), + expected: qdb.ConfigData{ + Schema: "http", + KeyValuePairs: map[string]string{ + "addr": addr, + }, + }, + }, } for _, tc := range testCases { @@ -231,6 +241,11 @@ func TestParserPathologicalCases(t *testing.T) { config: "", expectedErrMsgContains: "no schema separator found", }, + { + name: "empty config with semicolon", + config: ";", + expectedErrMsgContains: "no schema separator found", + }, { name: "no schema", config: "addr=localhost:9000", @@ -242,10 +257,15 @@ func TestParserPathologicalCases(t *testing.T) { expectedErrMsgContains: "'addr' key not found", }, { - name: "unescaped semicolon in password leads to invalid key character", + name: "unescaped semicolon in password leads to unexpected end of string (with trailing semicolon)", config: "http::addr=localhost:9000;username=test;password=pass;word;", expectedErrMsgContains: "unexpected end of", }, + { + name: "unescaped semicolon in password leads to unexpected end of string (no trailing semicolon)", + config: "http::addr=localhost:9000;username=test;password=pass;word", + expectedErrMsgContains: "unexpected end of", + }, } for _, tc := range testCases { @@ -344,7 +364,7 @@ func TestHappyCasesFromConf(t *testing.T) { }, { name: "password before username", - config: fmt.Sprintf("http::addr=%s;password=%s;username=%s;", + config: fmt.Sprintf("http::addr=%s;password=%s;username=%s", addr, pass, user), expectedOpts: []qdb.LineSenderOption{ qdb.WithHttp(), @@ -364,7 +384,7 @@ func TestHappyCasesFromConf(t *testing.T) { }, { name: "bearer token", - config: fmt.Sprintf("http::addr=%s;token=%s;", + config: fmt.Sprintf("http::addr=%s;token=%s", addr, token), expectedOpts: []qdb.LineSenderOption{ qdb.WithHttp(), @@ -453,9 +473,19 @@ func TestPathologicalCasesFromConf(t *testing.T) { expectedErrMsgContains: "unsupported option", }, { - name: "trailing semicolon required", - config: "http::addr=localhost:9000", - expectedErrMsgContains: "trailing semicolon", + name: "partial key at end", + config: "http::addr=localhost:9000;test", + expectedErrMsgContains: "unexpected end of string", + }, + { + name: "no value at end", + config: "http::addr=localhost:9000;username=", + expectedErrMsgContains: "empty value for key", + }, + { + name: "no value at end with semicolon", + config: "http::addr=localhost:9000;username=;", + expectedErrMsgContains: "empty value for key", }, }