Skip to content

Commit ebcf3cf

Browse files
committed
Test for absence of metrics from connections without pools.
Refactor tests to take string arguments rather than being parameterized with objects. This makes it easier to view/run the tests in Tests Explorer.
1 parent 19fb8e5 commit ebcf3cf

File tree

2 files changed

+70
-26
lines changed

2 files changed

+70
-26
lines changed

tests/MySqlConnector.Tests/Metrics/ConnectionsUsageTests.cs

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ namespace MySqlConnector.Tests.Metrics;
55
public class ConnectionsUsageTests : MetricsTestsBase
66
{
77
[Theory(Skip = MetricsSkip)]
8-
[MemberData(nameof(GetPoolCreators))]
9-
public void PoolCreators(IConnectionCreator connectionCreator)
8+
[InlineData("DataSource|true|")]
9+
[InlineData("DataSource|true|metrics-test")]
10+
[InlineData("Plain|true")]
11+
public void ConnectionsWithPoolsHaveMetrics(string connectionCreatorSpec)
1012
{
11-
connectionCreator.SetConnectionStringBuilder(CreateConnectionStringBuilder());
13+
using var connectionCreator = CreateConnectionCreator(connectionCreatorSpec, CreateConnectionStringBuilder());
1214
PoolName = connectionCreator.PoolName;
1315

1416
// no connections at beginning of test
@@ -55,15 +57,44 @@ public void PoolCreators(IConnectionCreator connectionCreator)
5557
AssertMeasurement("db.client.connections.usage|idle", 2);
5658
AssertMeasurement("db.client.connections.usage|used", 0);
5759
Assert.Equal(2, Server.ActiveConnections);
58-
59-
connectionCreator.Dispose();
6060
}
6161

62-
public static IEnumerable<object[]> GetPoolCreators()
62+
[Theory(Skip = MetricsSkip)]
63+
[InlineData("DataSource|false|")]
64+
[InlineData("DataSource|false|metrics-test")]
65+
[InlineData("Plain|false")]
66+
public void ConnectionsWithoutPoolsHaveNoMetrics(string connectionCreatorSpec)
6367
{
64-
yield return new object[] { new DataSourceConnectionCreator("metrics-test") };
65-
yield return new object[] { new DataSourceConnectionCreator(null) };
66-
yield return new object[] { new PlainConnectionCreator() };
68+
using var connectionCreator = CreateConnectionCreator(connectionCreatorSpec, CreateConnectionStringBuilder());
69+
PoolName = connectionCreator.PoolName;
70+
71+
// no connections at beginning of test
72+
AssertMeasurement("db.client.connections.usage", 0);
73+
AssertMeasurement("db.client.connections.usage|idle", 0);
74+
AssertMeasurement("db.client.connections.usage|used", 0);
75+
Assert.Equal(0, Server.ActiveConnections);
76+
77+
// opening a connection doesn't change connection counts
78+
using (var connection = connectionCreator.OpenConnection())
79+
{
80+
AssertMeasurement("db.client.connections.usage", 0);
81+
AssertMeasurement("db.client.connections.usage|idle", 0);
82+
AssertMeasurement("db.client.connections.usage|used", 0);
83+
Assert.Equal(1, Server.ActiveConnections);
84+
}
85+
86+
// closing it doesn't create an idle connection but closes it immediately
87+
AssertMeasurement("db.client.connections.usage", 0);
88+
AssertMeasurement("db.client.connections.usage|idle", 0);
89+
AssertMeasurement("db.client.connections.usage|used", 0);
90+
91+
// disposing the connection sends a COM_QUIT packet and immediately returns; give the in-proc server a chance to process it
92+
for (var retry = 0; retry < 20; retry++)
93+
{
94+
if (Server.ActiveConnections != 0)
95+
Thread.Sleep(1);
96+
}
97+
Assert.Equal(0, Server.ActiveConnections);
6798
}
6899

69100
[Fact(Skip = MetricsSkip)]
@@ -135,4 +166,15 @@ public async Task PendingRequestForOpenFromPool()
135166

136167
AssertMeasurement("db.client.connections.pending_requests", 0);
137168
}
169+
170+
private IConnectionCreator CreateConnectionCreator(string spec, MySqlConnectionStringBuilder connectionStringBuilder)
171+
{
172+
var parts = spec.Split('|');
173+
return parts[0] switch
174+
{
175+
"DataSource" => new DataSourceConnectionCreator(bool.Parse(parts[1]), parts[2] == "" ? null : parts[2], connectionStringBuilder),
176+
"Plain" => new PlainConnectionCreator(bool.Parse(parts[1]), connectionStringBuilder),
177+
_ => throw new NotSupportedException(),
178+
};
179+
}
138180
}

tests/MySqlConnector.Tests/Metrics/IConnectionCreator.cs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,46 @@ namespace MySqlConnector.Tests.Metrics;
44

55
public interface IConnectionCreator : IDisposable
66
{
7-
void SetConnectionStringBuilder(MySqlConnectionStringBuilder connectionStringBuilder);
87
string PoolName { get; }
98
MySqlConnection OpenConnection();
109
}
1110

12-
internal sealed class DataSourceConnectionCreator(string? poolName) : IConnectionCreator
11+
internal sealed class DataSourceConnectionCreator : IConnectionCreator
1312
{
14-
public void SetConnectionStringBuilder(MySqlConnectionStringBuilder connectionStringBuilder)
13+
public DataSourceConnectionCreator(bool usePooling, string? poolName, MySqlConnectionStringBuilder connectionStringBuilder)
1514
{
16-
m_connectionStringBuilder = connectionStringBuilder;
15+
connectionStringBuilder.Pooling = usePooling;
1716
m_dataSource = new MySqlDataSourceBuilder(connectionStringBuilder.ConnectionString)
18-
.UseName(m_poolName)
17+
.UseName(poolName)
1918
.Build();
20-
}
19+
PoolName = poolName ?? connectionStringBuilder!.GetConnectionString(includePassword: false);
20+
}
2121

22-
public MySqlConnection OpenConnection() => m_dataSource!.OpenConnection();
23-
public string PoolName => m_poolName ?? m_connectionStringBuilder!.GetConnectionString(includePassword: false);
24-
public override string ToString() => $"DataSource: {m_poolName ?? "(unnamed)"}";
22+
public MySqlConnection OpenConnection() => m_dataSource!.OpenConnection();
23+
public string PoolName { get; }
2524
public void Dispose() => m_dataSource!.Dispose();
2625

27-
private readonly string? m_poolName = poolName;
28-
private MySqlConnectionStringBuilder? m_connectionStringBuilder;
29-
private MySqlDataSource? m_dataSource;
26+
private readonly MySqlDataSource m_dataSource;
3027
}
3128

3229
internal sealed class PlainConnectionCreator : IConnectionCreator
3330
{
31+
public PlainConnectionCreator(bool usePooling, MySqlConnectionStringBuilder connectionStringBuilder)
32+
{
33+
connectionStringBuilder.Pooling = usePooling;
34+
m_connectionString = connectionStringBuilder.ConnectionString;
35+
PoolName = connectionStringBuilder.GetConnectionString(includePassword: false);
36+
}
37+
3438
public MySqlConnection OpenConnection()
3539
{
36-
var connection = new MySqlConnection(m_connectionStringBuilder!.ConnectionString);
40+
var connection = new MySqlConnection(m_connectionString);
3741
connection.Open();
3842
return connection;
3943
}
4044

41-
public void SetConnectionStringBuilder(MySqlConnectionStringBuilder connectionStringBuilder) => m_connectionStringBuilder = connectionStringBuilder;
42-
public string PoolName => m_connectionStringBuilder!.GetConnectionString(includePassword: false);
43-
public override string ToString() => "Plain";
45+
public string PoolName { get; }
4446
public void Dispose() { }
4547

46-
private MySqlConnectionStringBuilder? m_connectionStringBuilder;
48+
private readonly string m_connectionString;
4749
}

0 commit comments

Comments
 (0)