using System.Collections.Generic; using Npgsql; using pgLabII.PgUtils.ConnectionStrings; namespace pgLabII.PgUtils.Tests.ConnectionStrings; public class NpgsqlCodecTests { [Fact] public void Parse_Basic() { var codec = new NpgsqlCodec(); var res = codec.TryParse("Host=localhost;Port=5434;Database=testdb;Username=alice;Password=secret;SSL Mode=Require;Application Name=pgLab;Timeout=10"); Assert.True(res.IsSuccess); var d = res.Value; Assert.Single(d.Hosts); Assert.Equal("localhost", d.Hosts[0].Host); Assert.Equal((ushort)5434, 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(10, d.TimeoutSeconds); } [Fact] public void Parse_MultiHost_WithSinglePort() { var codec = new NpgsqlCodec(); var res = codec.TryParse("Host=host1,host2;Port=5433;Database=db;Username=u"); Assert.True(res.IsSuccess); var d = res.Value; Assert.Equal(2, d.Hosts.Count); Assert.Equal("host1", d.Hosts[0].Host); Assert.Equal((ushort)5433, d.Hosts[0].Port); Assert.Equal("host2", d.Hosts[1].Host); Assert.Equal((ushort)5433, d.Hosts[1].Port); } [Fact] public void Format_Basic_WithQuoting() { var codec = new NpgsqlCodec(); var d = new ConnectionDescriptor { Hosts = new [] { new HostEndpoint{ Host = "db.example.com", Port = 5432 } }, Database = "prod db", Username = "bob ", Password = "p;ss\"word", SslMode = SslMode.VerifyFull, ApplicationName = "cli app", TimeoutSeconds = 9, Properties = new Dictionary{{"Search Path","public"}} }; var res = codec.TryFormat(d); Assert.True(res.IsSuccess); var s = res.Value; Assert.Contains("Host=db.example.com", s); Assert.Contains("Port=5432", s); Assert.Contains("Database=prod db", s); Assert.Contains("Username='bob '", s); // Contains double-quote, no single-quote -> prefer single-quoted per DbConnectionStringBuilder-like behavior Assert.Contains("Password='p;ss" + '"' + "word'", s); Assert.Contains("SSL Mode=VerifyFull", s); Assert.Contains("Application Name=cli app", s); Assert.Contains("Timeout=9", s); Assert.Contains("Search Path=public", s); } [Fact] public void Roundtrip_ParseThenFormat() { var codec = new NpgsqlCodec(); var input = "Host=\"my host\";Database=postgres;Username=me;Password=\"with;quote\"\"\";Application Name=\"my app\";SSL Mode=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.Contains("Host=my host", s); Assert.Contains("Database=postgres", s); Assert.Contains("Username=me", s); // Contains double-quote, no single-quote -> prefer single-quoted per DbConnectionStringBuilder-like behavior; parsed value contains one double-quote Assert.Contains("Password='with;quote" + '"' + "'", s); Assert.Contains("Application Name=my app", s); Assert.Contains("SSL Mode=Prefer", s); } }