2025-10-26 14:14:00 +01:00
|
|
|
|
using Npgsql;
|
2025-08-30 20:32:35 +02:00
|
|
|
|
using pgLabII.PgUtils.ConnectionStrings;
|
|
|
|
|
|
|
|
|
|
|
|
namespace pgLabII.PgUtils.Tests.ConnectionStrings;
|
|
|
|
|
|
|
|
|
|
|
|
public class UrlCodecTests
|
|
|
|
|
|
{
|
|
|
|
|
|
[Fact]
|
|
|
|
|
|
public void Parse_Basic()
|
|
|
|
|
|
{
|
|
|
|
|
|
var codec = new UrlCodec();
|
|
|
|
|
|
var res = codec.TryParse("postgresql://alice:secret@localhost:5433/testdb?sslmode=require&application_name=pgLab&connect_timeout=12&search_path=public");
|
|
|
|
|
|
Assert.True(res.IsSuccess);
|
|
|
|
|
|
var d = res.Value;
|
|
|
|
|
|
Assert.Single(d.Hosts);
|
|
|
|
|
|
Assert.Equal("localhost", d.Hosts[0].Host);
|
|
|
|
|
|
Assert.Equal((ushort)5433, d.Hosts[0].Port);
|
|
|
|
|
|
Assert.Equal("testdb", d.Database);
|
|
|
|
|
|
Assert.Equal("alice", d.Username);
|
|
|
|
|
|
Assert.Equal("secret", d.Password);
|
|
|
|
|
|
Assert.Equal(SslMode.Require, d.SslMode);
|
|
|
|
|
|
Assert.Equal("pgLab", d.ApplicationName);
|
|
|
|
|
|
Assert.Equal(12, d.TimeoutSeconds);
|
|
|
|
|
|
Assert.True(d.Properties.ContainsKey("search_path"));
|
|
|
|
|
|
Assert.Equal("public", d.Properties["search_path"]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
|
public void Parse_MultiHost_WithIPv6()
|
|
|
|
|
|
{
|
|
|
|
|
|
var codec = new UrlCodec();
|
|
|
|
|
|
var res = codec.TryParse("postgresql://user@[::1]:5432,db.example.com:5433/db");
|
|
|
|
|
|
Assert.True(res.IsSuccess);
|
|
|
|
|
|
var d = res.Value;
|
|
|
|
|
|
Assert.Equal(2, d.Hosts.Count);
|
|
|
|
|
|
Assert.Equal("::1", d.Hosts[0].Host);
|
|
|
|
|
|
Assert.Equal((ushort)5432, d.Hosts[0].Port);
|
|
|
|
|
|
Assert.Equal("db.example.com", d.Hosts[1].Host);
|
|
|
|
|
|
Assert.Equal((ushort)5433, d.Hosts[1].Port);
|
|
|
|
|
|
Assert.Equal("db", d.Database);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
|
public void Format_Basic_WithEncoding()
|
|
|
|
|
|
{
|
|
|
|
|
|
var codec = new UrlCodec();
|
|
|
|
|
|
var d = new ConnectionDescriptor
|
|
|
|
|
|
{
|
|
|
|
|
|
Hosts = new [] { new HostEndpoint{ Host = "db.example.com", Port = 5432 } },
|
|
|
|
|
|
Database = "prod db",
|
|
|
|
|
|
Username = "bob",
|
|
|
|
|
|
Password = "p@ss w?rd",
|
|
|
|
|
|
SslMode = SslMode.VerifyFull,
|
|
|
|
|
|
ApplicationName = "cli app",
|
|
|
|
|
|
TimeoutSeconds = 7,
|
|
|
|
|
|
Properties = new Dictionary<string,string>{{"search_path","public"}}
|
|
|
|
|
|
};
|
|
|
|
|
|
var res = codec.TryFormat(d);
|
|
|
|
|
|
Assert.True(res.IsSuccess);
|
|
|
|
|
|
var s = res.Value;
|
|
|
|
|
|
Assert.StartsWith("postgresql://", s);
|
|
|
|
|
|
Assert.Contains("bob:p%40ss%20w%3Frd@db.example.com:5432", s);
|
|
|
|
|
|
Assert.Contains("/prod%20db", s);
|
|
|
|
|
|
Assert.Contains("sslmode=verify-full", s);
|
|
|
|
|
|
Assert.Contains("application_name=cli%20app", s);
|
|
|
|
|
|
Assert.Contains("connect_timeout=7", s);
|
|
|
|
|
|
Assert.Contains("search_path=public", s);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
|
public void Roundtrip_ParseThenFormat()
|
|
|
|
|
|
{
|
|
|
|
|
|
var codec = new UrlCodec();
|
|
|
|
|
|
var input = "postgresql://me:pa%3Ass@host1,host2:5433/postgres?application_name=my%20app&sslmode=prefer";
|
|
|
|
|
|
var parsed = codec.TryParse(input);
|
|
|
|
|
|
Assert.True(parsed.IsSuccess);
|
|
|
|
|
|
var formatted = codec.TryFormat(parsed.Value);
|
|
|
|
|
|
Assert.True(formatted.IsSuccess);
|
|
|
|
|
|
var s = formatted.Value;
|
|
|
|
|
|
Assert.StartsWith("postgresql://me:pa%3Ass@host1,host2:5433/postgres?", s);
|
|
|
|
|
|
Assert.Contains("application_name=my%20app", s);
|
|
|
|
|
|
Assert.Contains("sslmode=prefer", s);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|