Skip to content

Commit 5bb2d09

Browse files
committed
Move LeakReaders test to MySqlConnection.Tests.
This test can be run against the fake server since it only tests local connection pool behaviour.
1 parent c80e5eb commit 5bb2d09

File tree

3 files changed

+60
-37
lines changed

3 files changed

+60
-37
lines changed

tests/MySqlConnector.Tests/ConnectionTests.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using System;
1+
using System;
22
using System.Diagnostics;
3+
using System.Threading;
34
using System.Threading.Tasks;
45
using MySql.Data.MySqlClient;
56
using Xunit;
@@ -90,6 +91,32 @@ public async Task ConnectionLifeTime(uint lifeTime, uint delaySeconds, bool shou
9091
}
9192
}
9293

94+
[Fact]
95+
public void LeakReaders()
96+
{
97+
m_csb.Pooling = true;
98+
m_csb.MinimumPoolSize = 0;
99+
m_csb.MaximumPoolSize = 6;
100+
m_csb.ConnectionTimeout = 30u;
101+
102+
for (var i = 0; i < m_csb.MaximumPoolSize + 2; i++)
103+
{
104+
var connection = new MySqlConnection(m_csb.ConnectionString);
105+
connection.Open();
106+
107+
var cmd = connection.CreateCommand();
108+
cmd.CommandText = "SELECT 1;";
109+
var reader = cmd.ExecuteReader();
110+
Assert.True(reader.Read());
111+
112+
// have to GC for leaked connections to be removed from the pool
113+
GC.Collect();
114+
115+
// HACK: have to sleep (so that RecoverLeakedSessions is called in ConnectionPool.GetSessionAsync)
116+
Thread.Sleep(250);
117+
}
118+
}
119+
93120
private static async Task WaitForConditionAsync<T>(T expected, Func<T> getValue)
94121
{
95122
var sw = Stopwatch.StartNew();

tests/MySqlConnector.Tests/FakeMySqlServerConnection.cs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
using System;
1+
using System;
22
using System.IO;
33
using System.Net.Sockets;
44
using System.Text;
5+
using System.Text.RegularExpressions;
56
using System.Threading;
67
using System.Threading.Tasks;
78
using MySql.Data.MySqlClient;
@@ -41,14 +42,39 @@ public async Task RunAsync(TcpClient client, CancellationToken token)
4142
break;
4243

4344
case CommandKind.Ping:
44-
case CommandKind.Query:
4545
case CommandKind.ResetConnection:
46+
await SendAsync(stream, 1, WriteOk);
47+
break;
48+
49+
case CommandKind.Query:
50+
var query = Encoding.UTF8.GetString(bytes, 1, bytes.Length - 1);
51+
Match match;
52+
if (query == "SET NAMES utf8mb4 COLLATE utf8mb4_bin;")
53+
{
4654
await SendAsync(stream, 1, WriteOk);
55+
}
56+
else if ((match = Regex.Match(query, @"^SELECT ([0-9]+)(;|$)")).Success)
57+
{
58+
var number = match.Groups[1].Value;
59+
var data = new byte[number.Length + 1];
60+
data[0] = (byte) number.Length;
61+
Encoding.UTF8.GetBytes(number, 0, number.Length, data, 1);
62+
63+
await SendAsync(stream, 1, x => x.Write((byte) 1)); // one column
64+
await SendAsync(stream, 2, x => x.Write(new byte[] { 3, 0x64, 0x65, 0x66, 0, 0, 0, 1, 0x5F, 0, 0x0c, 0x3f, 0, 1, 0, 0, 0, 8, 0x81, 0, 0, 0, 0 })); // column definition
65+
await SendAsync(stream, 3, x => x.Write(new byte[] { 0xFE, 0, 0, 2, 0 })); // EOF
66+
await SendAsync(stream, 4, x => x.Write(data));
67+
await SendAsync(stream, 5, x => x.Write(new byte[] { 0xFE, 0, 0, 2, 0 })); // EOF
68+
}
69+
else
70+
{
71+
await SendAsync(stream, 1, x => WriteError(x, "Unhandled query: " + query));
72+
}
4773
break;
4874

4975
default:
5076
Console.WriteLine("** UNHANDLED ** {0}", (CommandKind) bytes[0]);
51-
await SendAsync(stream, 1, WriteError);
77+
await SendAsync(stream, 1, x => WriteError(x));
5278
break;
5379
}
5480
}
@@ -142,15 +168,15 @@ private static void WriteOk(BinaryWriter writer)
142168
writer.Write((ushort) 0); // warning count
143169
}
144170

145-
private static void WriteError(BinaryWriter writer)
171+
private static void WriteError(BinaryWriter writer, string message = "An unknown error occurred")
146172
{
147173
writer.Write((byte) 0xFF); // signature
148174
writer.Write((ushort) MySqlErrorCode.UnknownError); // error code
149175
writer.WriteRaw("#ERROR");
150-
writer.WriteRaw("An unknown error occurred");
176+
writer.WriteRaw(message);
151177
}
152178

153179
readonly FakeMySqlServer m_server;
154180
readonly int m_connectionId;
155181
}
156-
}
182+
}

tests/SideBySide/ConnectionPool.cs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -149,36 +149,6 @@ public void LeakConnections()
149149
}
150150
}
151151

152-
#if BASELINE
153-
[Fact(Skip = "Throws MySqlException - error connecting: Timeout expired")]
154-
#else
155-
[Fact]
156-
#endif
157-
public void LeakReaders()
158-
{
159-
var csb = AppConfig.CreateConnectionStringBuilder();
160-
csb.Pooling = true;
161-
csb.MinimumPoolSize = 0;
162-
csb.MaximumPoolSize = 6;
163-
csb.ConnectionTimeout = 3u;
164-
165-
for (int i = 0; i < csb.MaximumPoolSize + 2; i++)
166-
{
167-
var connection = new MySqlConnection(csb.ConnectionString);
168-
connection.Open();
169-
var cmd = connection.CreateCommand();
170-
cmd.CommandText = "SELECT 1";
171-
var reader = cmd.ExecuteReader();
172-
Assert.True(reader.Read());
173-
174-
// have to GC for leaked connections to be removed from the pool
175-
GC.Collect();
176-
177-
// HACK: have to sleep (so that RecoverLeakedSessions is called in ConnectionPool.GetSessionAsync?)
178-
Thread.Sleep(250);
179-
}
180-
}
181-
182152
[Fact]
183153
public async Task WaitTimeout()
184154
{

0 commit comments

Comments
 (0)