diff options
Diffstat (limited to 'pgruntime/target_test.go')
| -rw-r--r-- | pgruntime/target_test.go | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/pgruntime/target_test.go b/pgruntime/target_test.go new file mode 100644 index 0000000..d62721c --- /dev/null +++ b/pgruntime/target_test.go @@ -0,0 +1,111 @@ +// SPDX-FileCopyrightText: 2026 Stefan Majewsky <majewsky@gmx.net> +// SPDX-License-Identifier: Apache-2.0 + +package pgruntime_test + +import ( + "net/url" + "strings" + "testing" + + "go.xyrillian.de/gg/assert" + "go.xyrillian.de/gg/pgruntime" +) + +func TestParseConnectionTargetSuccess(t *testing.T) { + testCases := map[string]pgruntime.ConnectionTarget{ + // minimal case: just the required fields are set + `postgresql://alice@localhost/bookstore`: { + HostName: "localhost", + UserName: "alice", + DatabaseName: "bookstore", + }, + // maximal case: all required fields are set + `postgres://alice:swordfish@db.example.com:5432/bookstore?sslmode=prefer&application_name=frontdesk`: { + HostName: "db.example.com", + Port: "5432", + UserName: "alice", + Password: "swordfish", + DatabaseName: "bookstore", + ConnectionOptions: "sslmode=prefer&application_name=frontdesk", + }, + } + + for input, expected := range testCases { + t.Run(input, func(t *testing.T) { + u, err := url.Parse(input) + if !assert.ErrEqual(t, err, nil) { + t.FailNow() + } + parsed, err := pgruntime.ParseConnectionTargetFromURL(u) + if !assert.ErrEqual(t, err, nil) { + t.FailNow() + } + assert.Equal(t, parsed, expected) + serialized, err := parsed.IntoURL() + if !assert.ErrEqual(t, err, nil) { + t.FailNow() + } + // IntoURL() always uses postgres://, so this is not always an exact roundtrip + assert.Equal(t, serialized.String(), strings.ReplaceAll(input, "postgresql:", "postgres:")) + }) + } +} + +func TestParseConnectionTargetFailure(t *testing.T) { + testCases := map[string]string{ + `https://alice@db.example.com/foo?sslmode=prefer`: `expected scheme "postgres" or "postgresql", but got "https"`, + `postgres:foo?sslmode=prefer`: `expected authority component, but got rootless path "foo"`, + `postgres://alice@db.example.com/foo#sslmode=prefer`: `unexpected fragment "sslmode=prefer"`, + `postgres://alice@db.example.com::5432/foo?sslmode=prefer`: `malformed host "db.example.com::5432"`, + `postgres://alice@db.example.com/foo/bar?sslmode=prefer`: `malformed database name "foo/bar"`, + `postgres://alice@db.example.com/foo?sslmode=prefer;foo=bar`: `malformed connection options: invalid semicolon separator in query`, + } + for input, expected := range testCases { + t.Run(input, func(t *testing.T) { + u, err := url.Parse(input) + if !assert.ErrEqual(t, err, nil) { + t.FailNow() + } + _, err = pgruntime.ParseConnectionTargetFromURL(u) + assert.ErrEqual(t, err, "in ParseConnectionTargetFromURL: "+expected) + }) + } +} + +func TestSerializeConnectionOptions(t *testing.T) { + ct := pgruntime.ConnectionTarget{ + HostName: "localhost", + UserName: "alice", + DatabaseName: "bookstore", + } + + // cannot merge ConnectionOptions if the string part is malformed + ct.ConnectionOptions = `sslmode=prefer;foo=bar` + ct.ExtraConnectionOptions = url.Values{"application_name": {"frontdesk"}} + _, err := ct.IntoURL() + assert.ErrEqual(t, err, `in ConnectionTarget.IntoURL: malformed connection options: invalid semicolon separator in query`) + + // successful trivial merges + ct.ConnectionOptions = `sslmode=prefer` + ct.ExtraConnectionOptions = nil + u, err := ct.IntoURL() + if assert.ErrEqual(t, err, nil) { + assert.Equal(t, u.RawQuery, `sslmode=prefer`) + } + + ct.ConnectionOptions = "" + ct.ExtraConnectionOptions = url.Values{"application_name": {"frontdesk"}} + u, err = ct.IntoURL() + if assert.ErrEqual(t, err, nil) { + assert.Equal(t, u.RawQuery, `application_name=frontdesk`) + } + + // successful complex merge + ct.ConnectionOptions = `sslmode=prefer` + ct.ExtraConnectionOptions = url.Values{"application_name": {"frontdesk"}} + u, err = ct.IntoURL() + if assert.ErrEqual(t, err, nil) { + assert.Equal(t, u.RawQuery, `application_name=frontdesk&sslmode=prefer`) + } +} |
