Skip to content

Commit 2d01403

Browse files
authored
Test improvements (#344)
1 parent 4a650f3 commit 2d01403

File tree

4 files changed

+109
-12
lines changed

4 files changed

+109
-12
lines changed

src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Linq;
1212
using System.Reflection;
1313
using System.Text;
14+
using System.Threading;
1415
using System.Threading.Tasks;
1516
using Newtonsoft.Json;
1617
using Xunit;
@@ -445,14 +446,31 @@ public static string GenerateRandomCharacters(string prefix)
445446
return prefix + path;
446447
}
447448

448-
public static void RunNonQuery(string connectionString, string sql)
449+
public static void RunNonQuery(string connectionString, string sql, int numberOfRetries = 0)
449450
{
450-
using (SqlConnection connection = new SqlConnection(connectionString))
451-
using (SqlCommand command = connection.CreateCommand())
451+
int retries = 0;
452+
while (true)
452453
{
453-
connection.Open();
454-
command.CommandText = sql;
455-
command.ExecuteNonQuery();
454+
try
455+
{
456+
using (SqlConnection connection = new SqlConnection(connectionString))
457+
using (SqlCommand command = connection.CreateCommand())
458+
{
459+
connection.Open();
460+
command.CommandText = sql;
461+
command.ExecuteNonQuery();
462+
break;
463+
}
464+
}
465+
catch (Exception)
466+
{
467+
if (retries >= numberOfRetries)
468+
{
469+
throw;
470+
}
471+
retries++;
472+
Thread.Sleep(1000);
473+
}
456474
}
457475
}
458476

src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Common/InternalConnectionWrapper.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class InternalConnectionWrapper
2323
/// </summary>
2424
/// <param name="connection">Live outer connection to grab the inner connection from</param>
2525
/// <param name="supportKillByTSql">If true then we will query the server for this connection's SPID details (to be used in the KillConnectionByTSql method)</param>
26-
public InternalConnectionWrapper(SqlConnection connection, bool supportKillByTSql = false)
26+
public InternalConnectionWrapper(SqlConnection connection, bool supportKillByTSql = false, string originalConnectionString = "")
2727
{
2828
if (connection == null)
2929
throw new ArgumentNullException(nameof(connection));
@@ -33,6 +33,17 @@ public InternalConnectionWrapper(SqlConnection connection, bool supportKillByTSq
3333

3434
if (supportKillByTSql)
3535
{
36+
SqlConnectionStringBuilder csb = new SqlConnectionStringBuilder(ConnectionString);
37+
if (!csb.IntegratedSecurity &&
38+
string.IsNullOrWhiteSpace(originalConnectionString))
39+
{
40+
throw new ArgumentException("Must provide originalConnectionString if using supportKillByTSql and not using Integrated Security.");
41+
}
42+
else if (!string.IsNullOrWhiteSpace(originalConnectionString))
43+
{
44+
ConnectionString = originalConnectionString;
45+
}
46+
3647
// Save the SPID for later use
3748
using (SqlCommand command = new SqlCommand("SELECT @@SPID", connection))
3849
{

src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ConnectivityTests/ConnectivityTest.cs

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,9 @@ public static void ConnectionKilledTest()
207207
DataTestUtility.RunNonQuery(s_dbConnectionString, s_createTableCmd);
208208

209209
// Kill all the connections and set Database to SINGLE_USER Mode.
210-
DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseSingleCmd);
210+
DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseSingleCmd, 4);
211211
// Set Database back to MULTI_USER Mode
212-
DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseMultiCmd);
212+
DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseMultiCmd, 4);
213213

214214
// Execute SELECT statement.
215215
DataTestUtility.RunNonQuery(s_dbConnectionString, s_selectTableCmd);
@@ -222,8 +222,58 @@ public static void ConnectionKilledTest()
222222
finally
223223
{
224224
// Kill all the connections, set Database to SINGLE_USER Mode and drop Database
225-
DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseSingleCmd);
226-
DataTestUtility.RunNonQuery(s_connectionString, s_dropDatabaseCmd);
225+
DataTestUtility.RunNonQuery(s_connectionString, s_alterDatabaseSingleCmd, 4);
226+
DataTestUtility.RunNonQuery(s_connectionString, s_dropDatabaseCmd, 4);
227+
}
228+
}
229+
230+
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))]
231+
public static void ConnectionResiliencyTest()
232+
{
233+
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString);
234+
builder.ConnectRetryCount = 0;
235+
builder.ConnectRetryInterval = 5;
236+
237+
// No connection resiliency
238+
using (SqlConnection conn = new SqlConnection(builder.ConnectionString))
239+
{
240+
conn.Open();
241+
InternalConnectionWrapper wrapper = new InternalConnectionWrapper(conn, true, builder.ConnectionString);
242+
using (SqlCommand cmd = conn.CreateCommand())
243+
{
244+
cmd.CommandText = "SELECT TOP 1 * FROM dbo.Employees";
245+
wrapper.KillConnectionByTSql();
246+
bool cmdSuccess = false;
247+
try
248+
{
249+
cmd.ExecuteScalar();
250+
cmdSuccess = true;
251+
}
252+
// Windows always throws SqlException. Unix sometimes throws AggregateException against Azure SQL DB.
253+
catch (Exception ex) when (ex is SqlException || ex is AggregateException) { }
254+
Assert.False(cmdSuccess);
255+
}
256+
}
257+
258+
builder.ConnectRetryCount = 2;
259+
using (SqlConnection conn = new SqlConnection(builder.ConnectionString))
260+
{
261+
conn.Open();
262+
InternalConnectionWrapper wrapper = new InternalConnectionWrapper(conn, true, builder.ConnectionString);
263+
using (SqlCommand cmd = conn.CreateCommand())
264+
{
265+
cmd.CommandText = "SELECT TOP 1 * FROM dbo.Employees";
266+
using (SqlDataReader reader = cmd.ExecuteReader())
267+
while (reader.Read())
268+
{ }
269+
270+
wrapper.KillConnectionByTSql();
271+
272+
// Connection resiliency should reconnect transparently
273+
using (SqlDataReader reader = cmd.ExecuteReader())
274+
while (reader.Read())
275+
{ }
276+
}
227277
}
228278
}
229279
}

src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCredentialTest/SqlCredentialTest.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Linq;
77
using System.Security;
8+
using System.Threading;
89
using Xunit;
910

1011
namespace Microsoft.Data.SqlClient.ManualTesting.Tests
@@ -152,7 +153,24 @@ public static void OldCredentialsShouldFail()
152153
SecureString newPassword = new SecureString();
153154
"newPassword".ToCharArray().ToList().ForEach(x => newPassword.AppendChar(x));
154155
newPassword.MakeReadOnly();
155-
SqlConnection.ChangePassword(sqlConnectionStringBuilder.ConnectionString, credential, newPassword);
156+
int numberOfRetries = 0;
157+
while (true) // ChangePassword produces an intermittent server error during test runs so retry on failure
158+
{
159+
try
160+
{
161+
SqlConnection.ChangePassword(sqlConnectionStringBuilder.ConnectionString, credential, newPassword);
162+
break;
163+
}
164+
catch (SqlException)
165+
{
166+
if (numberOfRetries >= 4)
167+
{
168+
throw;
169+
}
170+
numberOfRetries++;
171+
Thread.Sleep(1000);
172+
}
173+
}
156174
using (SqlConnection conn5 = new SqlConnection(sqlConnectionStringBuilder.ConnectionString, new SqlCredential(user, password)))
157175
{
158176
Assert.Throws<SqlException>(() => conn5.Open());

0 commit comments

Comments
 (0)