diff --git a/core/conf/properties.go b/core/conf/properties.go index acd4fa617..1a675a85e 100644 --- a/core/conf/properties.go +++ b/core/conf/properties.go @@ -45,7 +45,7 @@ func LoadProperties(filename string, opts ...Option) (Properties, error) { raw := make(map[string]string) for i := range lines { - pair := strings.Split(lines[i], "=") + pair := strings.SplitN(lines[i], "=", 2) if len(pair) != 2 { // invalid property format return nil, &PropertyError{ diff --git a/core/conf/properties_test.go b/core/conf/properties_test.go index 19564c234..618b3512a 100644 --- a/core/conf/properties_test.go +++ b/core/conf/properties_test.go @@ -92,3 +92,70 @@ func TestLoadBadFile(t *testing.T) { _, err := LoadProperties("nosuchfile") assert.NotNil(t, err) } + +func TestProperties_valueWithEqualSymbols(t *testing.T) { + text := `# test with equal symbols in value + db.url=postgres://localhost:5432/db?param=value + math.equation=a=b=c + base64.data=SGVsbG8=World=Test= + url.with.params=http://example.com?foo=bar&baz=qux + empty.value= + key.with.space = value = with = equals` + tmpfile, err := fs.TempFilenameWithText(text) + assert.Nil(t, err) + defer os.Remove(tmpfile) + + props, err := LoadProperties(tmpfile) + assert.Nil(t, err) + assert.Equal(t, "postgres://localhost:5432/db?param=value", props.GetString("db.url")) + assert.Equal(t, "a=b=c", props.GetString("math.equation")) + assert.Equal(t, "SGVsbG8=World=Test=", props.GetString("base64.data")) + assert.Equal(t, "http://example.com?foo=bar&baz=qux", props.GetString("url.with.params")) + assert.Equal(t, "", props.GetString("empty.value")) + assert.Equal(t, "value = with = equals", props.GetString("key.with.space")) +} + +func TestProperties_edgeCases(t *testing.T) { + tests := []struct { + name string + content string + wantErr bool + errMsg string + }{ + { + name: "no equal sign", + content: "invalid line without equal", + wantErr: true, + }, + { + name: "only equal sign", + content: "=", + wantErr: false, // "=" 会被解析为空 key 和空 value,len(pair) == 2,是合法的 + }, + { + name: "empty key", + content: "=value", + wantErr: false, // 空 key 也会被 trim,但 len(pair) == 2 所以不会报错 + }, + { + name: "equal at end", + content: "key.name=", + wantErr: false, // 空 value 是合法的 + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmpfile, err := fs.TempFilenameWithText(tt.content) + assert.Nil(t, err) + defer os.Remove(tmpfile) + + _, err = LoadProperties(tmpfile) + if tt.wantErr { + assert.NotNil(t, err, "expected error for case: %s", tt.name) + } else { + assert.Nil(t, err, "unexpected error for case: %s", tt.name) + } + }) + } +}