Skip to content

Commit d3ee11b

Browse files
committed
Implement Ping and PingAsync. Fixes #260
1 parent 9a4ec49 commit d3ee11b

File tree

6 files changed

+110
-11
lines changed

6 files changed

+110
-11
lines changed

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ private async Task<string> GetRsaPublicKeyAsync(string switchRequestName, Connec
507507
throw new MySqlException("Authentication method '{0}' failed. Either use a secure connection, specify the server's RSA public key with ServerRSAPublicKeyFile, or set AllowPublicKeyRetrieval=True.".FormatInvariant(switchRequestName));
508508
}
509509

510-
public async Task<bool> TryPingAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)
510+
public async ValueTask<bool> TryPingAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)
511511
{
512512
VerifyState(State.Connected);
513513

src/MySqlConnector/MySql.Data.MySqlClient/MySqlConnection.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,27 @@ private async Task ChangeDatabaseAsync(IOBehavior ioBehavior, string databaseNam
135135

136136
public new MySqlCommand CreateCommand() => (MySqlCommand) base.CreateCommand();
137137

138+
public bool Ping() => PingAsync(IOBehavior.Synchronous, CancellationToken.None).GetAwaiter().GetResult();
139+
public Task<bool> PingAsync() => PingAsync((m_connectionSettings?.ForceSynchronous ?? false) ? IOBehavior.Synchronous : IOBehavior.Asynchronous, CancellationToken.None).AsTask();
140+
public Task<bool> PingAsync(CancellationToken cancellationToken) => PingAsync((m_connectionSettings?.ForceSynchronous ?? false) ? IOBehavior.Synchronous : IOBehavior.Asynchronous, cancellationToken).AsTask();
141+
142+
private async ValueTask<bool> PingAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)
143+
{
144+
if (m_session == null)
145+
return false;
146+
try
147+
{
148+
if (await m_session.TryPingAsync(ioBehavior, cancellationToken).ConfigureAwait(false))
149+
return true;
150+
}
151+
catch (InvalidOperationException)
152+
{
153+
}
154+
155+
SetState(ConnectionState.Closed);
156+
return false;
157+
}
158+
138159
public override void Open() => OpenAsync(IOBehavior.Synchronous, CancellationToken.None).GetAwaiter().GetResult();
139160

140161
public override Task OpenAsync(CancellationToken cancellationToken) =>

tests/MySqlConnector.Tests/ConnectionTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,31 @@ public void IncompleteServerHandshake()
152152
}
153153
}
154154

155+
[Fact]
156+
public void Ping()
157+
{
158+
using (var connection = new MySqlConnection(m_csb.ConnectionString))
159+
{
160+
connection.Open();
161+
Assert.Equal(ConnectionState.Open, connection.State);
162+
Assert.True(connection.Ping());
163+
Assert.Equal(ConnectionState.Open, connection.State);
164+
}
165+
}
166+
167+
[Fact]
168+
public void PingWhenClosed()
169+
{
170+
using (var connection = new MySqlConnection(m_csb.ConnectionString))
171+
{
172+
connection.Open();
173+
Assert.Equal(ConnectionState.Open, connection.State);
174+
m_server.Stop();
175+
Assert.False(connection.Ping());
176+
Assert.Equal(ConnectionState.Closed, connection.State);
177+
}
178+
}
179+
155180
private static async Task WaitForConditionAsync<T>(T expected, Func<T> getValue)
156181
{
157182
var sw = Stopwatch.StartNew();

tests/MySqlConnector.Tests/FakeMySqlServer.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,21 @@ public void Start()
2525

2626
public void Stop()
2727
{
28-
m_cts.Cancel();
29-
m_tcpListener.Stop();
30-
try
31-
{
32-
Task.WaitAll(m_tasks.ToArray());
33-
}
34-
catch (AggregateException)
28+
if (m_cts != null)
3529
{
30+
m_cts.Cancel();
31+
m_tcpListener.Stop();
32+
try
33+
{
34+
Task.WaitAll(m_tasks.ToArray());
35+
}
36+
catch (AggregateException)
37+
{
38+
}
39+
m_tasks.Clear();
40+
m_cts.Dispose();
41+
m_cts = null;
3642
}
37-
m_tasks.Clear();
38-
m_cts.Dispose();
39-
m_cts = null;
4043
}
4144

4245
public int Port => ((IPEndPoint) m_tcpListener.LocalEndpoint).Port;

tests/SideBySide/ConnectAsync.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,32 @@ public async Task CachingSha2WithoutSecureConnection()
312312
}
313313
}
314314

315+
#if !BASELINE
316+
[Fact]
317+
public async Task PingNoConnection()
318+
{
319+
using (var connection = new MySqlConnection())
320+
Assert.False(await connection.PingAsync());
321+
}
322+
323+
[Fact]
324+
public async Task PingBeforeConnecting()
325+
{
326+
using (var connection = new MySqlConnection(AppConfig.ConnectionString))
327+
Assert.False(await connection.PingAsync());
328+
}
329+
330+
[Fact]
331+
public async Task PingConnection()
332+
{
333+
using (var connection = new MySqlConnection(AppConfig.ConnectionString))
334+
{
335+
await connection.OpenAsync();
336+
Assert.True(await connection.PingAsync());
337+
}
338+
}
339+
#endif
340+
315341
readonly DatabaseFixture m_database;
316342
}
317343

tests/SideBySide/ConnectSync.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,30 @@ public void Sha256WithoutSecureConnection()
367367
}
368368
}
369369

370+
[Fact]
371+
public void PingNoConnection()
372+
{
373+
using (var connection = new MySqlConnection())
374+
Assert.False(connection.Ping());
375+
}
376+
377+
[Fact]
378+
public void PingBeforeConnecting()
379+
{
380+
using (var connection = new MySqlConnection(AppConfig.ConnectionString))
381+
Assert.False(connection.Ping());
382+
}
383+
384+
[Fact]
385+
public void PingConnection()
386+
{
387+
using (var connection = new MySqlConnection(AppConfig.ConnectionString))
388+
{
389+
connection.Open();
390+
Assert.True(connection.Ping());
391+
}
392+
}
393+
370394
readonly DatabaseFixture m_database;
371395
}
372396
}

0 commit comments

Comments
 (0)