diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs
index e22988b35d..b96e6f654d 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnection.cs
@@ -1937,8 +1937,10 @@ private Task InternalOpenAsync(SqlConnectionOverrides overrides, CancellationTok
s_diagnosticListener.IsEnabled(SqlClientConnectionOpenError.Name))
{
result.Task.ContinueWith(
- continuationAction: s_openAsyncComplete,
+ continuationAction: static (task, state) => s_openAsyncComplete(task, state),
state: operationId, // connection is passed in TaskCompletionSource async state
+ cancellationToken: CancellationToken.None, // we want the continuation task to run even if the original operation was cancelled
+ continuationOptions: TaskContinuationOptions.ExecuteSynchronously,
scheduler: TaskScheduler.Default
);
}
diff --git a/src/Microsoft.Data.SqlClient/tests/Directory.Packages.props b/src/Microsoft.Data.SqlClient/tests/Directory.Packages.props
index 78ea36f1fa..72bddcc898 100644
--- a/src/Microsoft.Data.SqlClient/tests/Directory.Packages.props
+++ b/src/Microsoft.Data.SqlClient/tests/Directory.Packages.props
@@ -12,7 +12,6 @@
-
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTests.csproj b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTests.csproj
index 336838b068..25a1d53d0d 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTests.csproj
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTests.csproj
@@ -342,7 +342,8 @@
+ Condition="'$(ReferenceType)' != 'Package'"
+ Private="true" />
@@ -360,7 +361,6 @@
-
@@ -395,7 +395,6 @@
-
@@ -422,4 +421,5 @@
+
diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/DiagnosticTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/DiagnosticTest.cs
index f550e7db70..db49fc7c32 100644
--- a/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/DiagnosticTest.cs
+++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/TracingTests/DiagnosticTest.cs
@@ -2,31 +2,30 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using System.Collections;
+using System.Collections.Generic;
+using System.Data;
using System.Diagnostics;
using System.Reflection;
+using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Xml;
using Microsoft.SqlServer.TDS;
using Microsoft.SqlServer.TDS.Done;
using Microsoft.SqlServer.TDS.EndPoint;
using Microsoft.SqlServer.TDS.Error;
-using Microsoft.SqlServer.TDS.Servers;
using Microsoft.SqlServer.TDS.SQLBatch;
+using Microsoft.SqlServer.TDS.Servers;
using Xunit;
-using System.Runtime.CompilerServices;
-using System;
-using System.Data;
-using Microsoft.DotNet.RemoteExecutor;
namespace Microsoft.Data.SqlClient.ManualTesting.Tests
{
- // TODO(ADO-39873): Re-enable these tests after addressing their flakiness.
- [Trait("Category", "flaky")]
+ // Serialized execution: DiagnosticListener is global state, so these tests
+ // must not run in parallel with each other.
+ [Collection("DiagnosticTests")]
public class DiagnosticTest
{
- private const string BadConnectionString = "data source = bad; initial catalog = bad; integrated security = true; connection timeout = 1;";
-
private const string WriteCommandBefore = "Microsoft.Data.SqlClient.WriteCommandBefore";
private const string WriteCommandAfter = "Microsoft.Data.SqlClient.WriteCommandAfter";
private const string WriteCommandError = "Microsoft.Data.SqlClient.WriteCommandError";
@@ -35,969 +34,441 @@ public class DiagnosticTest
private const string WriteConnectionOpenError = "Microsoft.Data.SqlClient.WriteConnectionOpenError";
private const string WriteConnectionCloseBefore = "Microsoft.Data.SqlClient.WriteConnectionCloseBefore";
private const string WriteConnectionCloseAfter = "Microsoft.Data.SqlClient.WriteConnectionCloseAfter";
- private const string WriteConnectionCloseError = "Microsoft.Data.SqlClient.WriteConnectionCloseError";
+ private const string BadConnectionString = "data source = bad; initial catalog = bad; integrated security = true; connection timeout = 1;";
+
+ #region Sync tests
[Fact]
public void ExecuteScalarTest()
{
- RemoteExecutor.Invoke(() =>
+ CollectStatisticsDiagnostics(connectionString =>
{
- CollectStatisticsDiagnostics(connectionString =>
- {
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();";
-
- conn.Open();
- cmd.ExecuteScalar();
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();", conn);
+ conn.Open();
+ cmd.ExecuteScalar();
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
public void ExecuteScalarErrorTest()
{
- RemoteExecutor.Invoke(() =>
+ CollectStatisticsDiagnostics(connectionString =>
{
- CollectStatisticsDiagnostics(connectionString =>
- {
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT 1 / 0;";
-
- conn.Open();
- Assert.Throws(() => cmd.ExecuteScalar());
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT 1 / 0;", conn);
+ conn.Open();
+ Assert.Throws(() => cmd.ExecuteScalar());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
public void ExecuteNonQueryTest()
{
- RemoteExecutor.Invoke(() =>
+ CollectStatisticsDiagnostics(connectionString =>
{
- CollectStatisticsDiagnostics(connectionString =>
- {
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();";
-
- conn.Open();
- cmd.ExecuteNonQuery();
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();", conn);
+ conn.Open();
+ cmd.ExecuteNonQuery();
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
public void ExecuteNonQueryErrorTest()
{
- RemoteExecutor.Invoke(() =>
+ CollectStatisticsDiagnostics(connectionString =>
{
- CollectStatisticsDiagnostics(connectionString =>
- {
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT 1 / 0;";
-
- // Limiting the command timeout to 3 seconds. This should be lower than the Process timeout.
- cmd.CommandTimeout = 3;
- conn.Open();
-
- Assert.Throws(() => cmd.ExecuteNonQuery());
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT 1 / 0;", conn);
+ cmd.CommandTimeout = 3;
+ conn.Open();
+ Assert.Throws(() => cmd.ExecuteNonQuery());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
public void ExecuteReaderTest()
{
- RemoteExecutor.Invoke(() =>
+ CollectStatisticsDiagnostics(connectionString =>
{
- CollectStatisticsDiagnostics(connectionString =>
- {
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();";
-
- conn.Open();
- SqlDataReader reader = cmd.ExecuteReader();
- while (reader.Read())
- {
- // Read until end.
- }
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();", conn);
+ conn.Open();
+ using SqlDataReader reader = cmd.ExecuteReader();
+ while (reader.Read()) { }
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
public void ExecuteReaderErrorTest()
{
- RemoteExecutor.Invoke(() =>
+ CollectStatisticsDiagnostics(connectionString =>
{
- CollectStatisticsDiagnostics(connectionString =>
- {
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT 1 / 0;";
-
- conn.Open();
- // @TODO: TestTdsServer should not throw on ExecuteReader, it should throw on reader.Read
- Assert.Throws(() => cmd.ExecuteReader());
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT 1 / 0;", conn);
+ conn.Open();
+ Assert.Throws(() => cmd.ExecuteReader());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
public void ExecuteReaderWithCommandBehaviorTest()
{
- RemoteExecutor.Invoke(() =>
+ CollectStatisticsDiagnostics(connectionString =>
{
- CollectStatisticsDiagnostics(connectionString =>
- {
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();";
-
- conn.Open();
- SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.Default);
- while (reader.Read())
- {
- // Read to end
- }
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();", conn);
+ conn.Open();
+ using SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.Default);
+ while (reader.Read()) { }
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
- // Synapse: Parse error at line: 1, column: 27: Incorrect syntax near 'for'.
- [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
+ [Fact]
public void ExecuteXmlReaderTest()
{
- RemoteExecutor.Invoke(() =>
+ // The TDS test server does not return XML-formatted results, so
+ // ExecuteXmlReader will throw. We verify the error diagnostic path.
+ CollectStatisticsDiagnostics(connectionString =>
{
- CollectStatisticsDiagnostics(_ =>
- {
- // @TODO: Test TDS server doesn't support ExecuteXmlReader, so connect to real server as workaround
- using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString))
- using (SqlCommand cmd = new SqlCommand())
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT TOP 10 * FROM sys.objects FOR xml auto, xmldata;";
-
- conn.Open();
- XmlReader reader = cmd.ExecuteXmlReader();
- while (reader.Read())
- {
- // Read to end
- }
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT TOP 10 * FROM sys.objects FOR xml auto, xmldata;", conn);
+ conn.Open();
+ Assert.Throws(() => cmd.ExecuteXmlReader());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
- [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))]
+ [Fact]
public void ExecuteXmlReaderErrorTest()
{
- RemoteExecutor.Invoke(() =>
+ CollectStatisticsDiagnostics(connectionString =>
{
- CollectStatisticsDiagnostics(connectionString =>
- {
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT *, baddata = 1 / 0 FROM sys.objects FOR xml auto, xmldata;";
-
- conn.Open();
- // @TODO: TestTdsServer should not throw on ExecuteXmlReader, should throw on reader.Read
- Assert.Throws(() => cmd.ExecuteXmlReader());
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT *, baddata = 1 / 0 FROM sys.objects FOR xml auto, xmldata;", conn);
+ conn.Open();
+ Assert.Throws(() => cmd.ExecuteXmlReader());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
- public void ExecuteScalarAsyncTest()
+ public void ConnectionOpenTest()
{
- RemoteExecutor.Invoke(() =>
+ CollectStatisticsDiagnostics(connectionString =>
{
- CollectStatisticsDiagnosticsAsync(async connectionString =>
- {
-#if NET
- await using (SqlConnection conn = new SqlConnection(connectionString))
- await using (SqlCommand cmd = new SqlCommand())
-#else
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
-#endif
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();";
-
- conn.Open();
- await cmd.ExecuteScalarAsync();
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]).Wait();
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(connectionString);
+ conn.Open();
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
- public void ExecuteScalarAsyncErrorTest()
+ public void ConnectionOpenErrorTest()
{
- RemoteExecutor.Invoke(() =>
+ CollectStatisticsDiagnostics(_ =>
{
- CollectStatisticsDiagnosticsAsync(async connectionString =>
- {
-#if NET
- await using (SqlConnection conn = new SqlConnection(connectionString))
- await using (SqlCommand cmd = new SqlCommand())
-#else
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
-#endif
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT 1 / 0;";
-
- conn.Open();
- await Assert.ThrowsAsync(() => cmd.ExecuteScalarAsync());
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]).Wait();
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ using SqlConnection conn = new(BadConnectionString);
+ Assert.Throws(() => conn.Open());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenError]);
}
+ #endregion
+
+ #region Async tests
+
[Fact]
- public void ExecuteNonQueryAsyncTest()
+ public async Task ExecuteScalarAsyncTest()
{
- RemoteExecutor.Invoke(() =>
+ await CollectStatisticsDiagnosticsAsync(async connectionString =>
{
- CollectStatisticsDiagnosticsAsync(async connectionString =>
- {
#if NET
- await using (SqlConnection conn = new SqlConnection(connectionString))
- await using (SqlCommand cmd = new SqlCommand())
+ await using SqlConnection conn = new(connectionString);
+ await using SqlCommand cmd = new("SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();", conn);
#else
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();", conn);
#endif
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();";
-
- conn.Open();
- await cmd.ExecuteNonQueryAsync();
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]).Wait();
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ conn.Open();
+ await cmd.ExecuteScalarAsync();
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
- public void ExecuteNonQueryAsyncErrorTest()
+ public async Task ExecuteScalarAsyncErrorTest()
{
- RemoteExecutor.Invoke(() =>
+ await CollectStatisticsDiagnosticsAsync(async connectionString =>
{
- CollectStatisticsDiagnosticsAsync(async connectionString =>
- {
#if NET
- await using (SqlConnection conn = new SqlConnection(connectionString))
- await using (SqlCommand cmd = new SqlCommand())
+ await using SqlConnection conn = new(connectionString);
+ await using SqlCommand cmd = new("SELECT 1 / 0;", conn);
#else
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT 1 / 0;", conn);
#endif
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT 1 / 0;";
-
- conn.Open();
- await Assert.ThrowsAsync(() => cmd.ExecuteNonQueryAsync());
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]).Wait();
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ conn.Open();
+ await Assert.ThrowsAsync(() => cmd.ExecuteScalarAsync());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
- public void ExecuteReaderAsyncTest()
+ public async Task ExecuteNonQueryAsyncTest()
{
- RemoteExecutor.Invoke(() =>
+ await CollectStatisticsDiagnosticsAsync(async connectionString =>
{
- CollectStatisticsDiagnosticsAsync(async connectionString =>
- {
#if NET
- await using (SqlConnection conn = new SqlConnection(connectionString))
- await using (SqlCommand cmd = new SqlCommand())
+ await using SqlConnection conn = new(connectionString);
+ await using SqlCommand cmd = new("SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();", conn);
#else
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();", conn);
#endif
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();";
-
- conn.Open();
- SqlDataReader reader = await cmd.ExecuteReaderAsync();
- while (reader.Read())
- {
- // Read to end
- }
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]).Wait();
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ conn.Open();
+ await cmd.ExecuteNonQueryAsync();
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
- public void ExecuteReaderAsyncErrorTest()
+ public async Task ExecuteNonQueryAsyncErrorTest()
{
- RemoteExecutor.Invoke(() =>
+ await CollectStatisticsDiagnosticsAsync(async connectionString =>
{
- CollectStatisticsDiagnosticsAsync(async connectionString =>
- {
#if NET
- await using (SqlConnection conn = new SqlConnection(connectionString))
- await using (SqlCommand cmd = new SqlCommand())
+ await using SqlConnection conn = new(connectionString);
+ await using SqlCommand cmd = new("SELECT 1 / 0;", conn);
#else
- using (SqlConnection conn = new SqlConnection(connectionString))
- using (SqlCommand cmd = new SqlCommand())
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT 1 / 0;", conn);
#endif
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT 1 / 0;";
-
- conn.Open();
- // @TODO: TestTdsServer should not throw on ExecuteReader, should throw on reader.Read
- await Assert.ThrowsAsync(() => cmd.ExecuteReaderAsync());
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]).Wait();
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ conn.Open();
+ await Assert.ThrowsAsync(() => cmd.ExecuteNonQueryAsync());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
- // Synapse: Parse error at line: 1, column: 27: Incorrect syntax near 'for'.
- [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
- public void ExecuteXmlReaderAsyncTest()
+ [Fact]
+ public async Task ExecuteReaderAsyncTest()
{
- // @TODO: TestTdsServer does not handle xml reader, so connect to a real server as a workaround
- RemoteExecutor.Invoke(() =>
+ await CollectStatisticsDiagnosticsAsync(async connectionString =>
{
- CollectStatisticsDiagnosticsAsync(async _ =>
- {
#if NET
- await using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString))
- await using (SqlCommand cmd = new SqlCommand())
+ await using SqlConnection conn = new(connectionString);
+ await using SqlCommand cmd = new("SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();", conn);
#else
- using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString))
- using (SqlCommand cmd = new SqlCommand())
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT [name], [state] FROM [sys].[databases] WHERE [name] = db_name();", conn);
#endif
- {
- cmd.Connection = conn;
- cmd.CommandText = "SELECT TOP 10 * FROM sys.objects FOR xml auto, xmldata;";
-
- conn.Open();
- XmlReader reader = await cmd.ExecuteXmlReaderAsync();
- while (reader.Read())
- {
- // Read to end
- }
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]).Wait();
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ conn.Open();
+ using SqlDataReader reader = await cmd.ExecuteReaderAsync();
+ while (reader.Read()) { }
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
- public void ExecuteXmlReaderAsyncErrorTest()
+ public async Task ExecuteReaderAsyncErrorTest()
{
- // @TODO: TestTdsServer does not handle xml reader, so connect to a real server as a workaround
- RemoteExecutor.Invoke(() =>
+ await CollectStatisticsDiagnosticsAsync(async connectionString =>
{
-
- CollectStatisticsDiagnosticsAsync(async _ =>
- {
#if NET
- await using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString))
- await using (SqlCommand cmd = new SqlCommand())
+ await using SqlConnection conn = new(connectionString);
+ await using SqlCommand cmd = new("SELECT 1 / 0;", conn);
#else
- using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString))
- using (SqlCommand cmd = new SqlCommand())
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT 1 / 0;", conn);
#endif
- {
- cmd.Connection = conn;
- cmd.CommandText = "select *, baddata = 1 / 0 from sys.objects for xml auto, xmldata;";
-
- // @TODO: Since this test uses a real database connection, the exception is
- // thrown during reader.Read. (ie, TestTdsServer does not obey proper
- // exception behavior)
- // NB: As a result of the exception being thrown during reader.Read,
- // cmd.ExecuteXmlReaderAsync returns successfully. This means that we receive
- // a WriteCommandAfter event rather than WriteCommandError.
- await conn.OpenAsync();
- XmlReader reader = await cmd.ExecuteXmlReaderAsync();
- await Assert.ThrowsAsync(() => reader.ReadAsync());
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]).Wait();
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ conn.Open();
+ await Assert.ThrowsAsync(() => cmd.ExecuteReaderAsync());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
- public void ConnectionOpenTest()
+ public async Task ExecuteXmlReaderAsyncTest()
{
- RemoteExecutor.Invoke(() =>
+ // The TDS test server does not return XML-formatted results, so
+ // ExecuteXmlReaderAsync will throw. We verify the error diagnostic path.
+ await CollectStatisticsDiagnosticsAsync(async connectionString =>
{
- CollectStatisticsDiagnostics(connectionString =>
- {
- using (SqlConnection sqlConnection = new SqlConnection(connectionString))
- {
- sqlConnection.Open();
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+#if NET
+ await using SqlConnection conn = new(connectionString);
+ await using SqlCommand cmd = new("SELECT TOP 10 * FROM sys.objects FOR xml auto, xmldata;", conn);
+#else
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT TOP 10 * FROM sys.objects FOR xml auto, xmldata;", conn);
+#endif
+ conn.Open();
+ await Assert.ThrowsAsync(() => cmd.ExecuteXmlReaderAsync());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
- public void ConnectionOpenErrorTest()
+ public async Task ExecuteXmlReaderAsyncErrorTest()
{
- RemoteExecutor.Invoke(() =>
+ await CollectStatisticsDiagnosticsAsync(async connectionString =>
{
- CollectStatisticsDiagnostics(_ =>
- {
- using (SqlConnection sqlConnection = new SqlConnection(BadConnectionString))
- {
- Assert.Throws(() => sqlConnection.Open());
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenError]);
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+#if NET
+ await using SqlConnection conn = new(connectionString);
+ await using SqlCommand cmd = new("SELECT *, baddata = 1 / 0 FROM sys.objects FOR xml auto, xmldata;", conn);
+#else
+ using SqlConnection conn = new(connectionString);
+ using SqlCommand cmd = new("SELECT *, baddata = 1 / 0 FROM sys.objects FOR xml auto, xmldata;", conn);
+#endif
+ conn.Open();
+ Assert.Throws(() => cmd.ExecuteXmlReader());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteCommandBefore, WriteCommandError, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
- public void ConnectionOpenAsyncTest()
+ public async Task ConnectionOpenAsyncTest()
{
- RemoteExecutor.Invoke(() =>
+ await CollectStatisticsDiagnosticsAsync(async connectionString =>
{
- CollectStatisticsDiagnosticsAsync(async connectionString =>
- {
#if NET
- await using (SqlConnection sqlConnection = new SqlConnection(connectionString))
+ await using SqlConnection conn = new(connectionString);
#else
- using (SqlConnection sqlConnection = new SqlConnection(connectionString))
+ using SqlConnection conn = new(connectionString);
#endif
- {
- await sqlConnection.OpenAsync();
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]).Wait();
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ await conn.OpenAsync();
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenAfter, WriteConnectionCloseBefore, WriteConnectionCloseAfter]);
}
[Fact]
- public void ConnectionOpenAsyncErrorTest()
+ public async Task ConnectionOpenAsyncErrorTest()
{
- RemoteExecutor.Invoke(() =>
+ await CollectStatisticsDiagnosticsAsync(async _ =>
{
- CollectStatisticsDiagnosticsAsync(async _ =>
- {
#if NET
- await using (SqlConnection sqlConnection = new SqlConnection(BadConnectionString))
+ await using SqlConnection conn = new(BadConnectionString);
#else
- using (SqlConnection sqlConnection = new SqlConnection(BadConnectionString))
+ using SqlConnection conn = new(BadConnectionString);
#endif
- {
- await Assert.ThrowsAsync(() => sqlConnection.OpenAsync());
- }
- }, [WriteConnectionOpenBefore, WriteConnectionOpenError]).Wait();
- return RemoteExecutor.SuccessExitCode;
- }).Dispose();
+ await Assert.ThrowsAsync(() => conn.OpenAsync());
+ }, [WriteConnectionOpenBefore, WriteConnectionOpenError]);
}
- private static void CollectStatisticsDiagnostics(Action sqlOperation, string[] expectedDiagnostics, [CallerMemberName] string methodName = "")
- {
- bool statsLogged = false;
- bool operationHasError = false;
- Guid beginOperationId = Guid.Empty;
-
- FakeDiagnosticListenerObserver diagnosticListenerObserver = new FakeDiagnosticListenerObserver(kvp =>
- {
- IDictionary statistics;
-
- if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteCommandBefore"))
- {
- Assert.NotNull(kvp.Value);
-
- Guid retrievedOperationId = GetPropertyValueFromType(kvp.Value, "OperationId");
- Assert.NotEqual(retrievedOperationId, Guid.Empty);
-
- SqlCommand sqlCommand = GetPropertyValueFromType(kvp.Value, "Command");
- Assert.NotNull(sqlCommand);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- if (sqlCommand.Connection.State == ConnectionState.Open)
- {
- Assert.NotEqual(connectionId, Guid.Empty);
- }
-
- beginOperationId = retrievedOperationId;
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteCommandAfter"))
- {
- Assert.NotNull(kvp.Value);
-
- Guid retrievedOperationId = GetPropertyValueFromType(kvp.Value, "OperationId");
- Assert.NotEqual(retrievedOperationId, Guid.Empty);
-
- SqlCommand sqlCommand = GetPropertyValueFromType(kvp.Value, "Command");
- Assert.NotNull(sqlCommand);
-
- statistics = GetPropertyValueFromType(kvp.Value, "Statistics");
- if (!operationHasError)
- {
- Assert.NotNull(statistics);
- }
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- if (sqlCommand.Connection.State == ConnectionState.Open)
- {
- Assert.NotEqual(connectionId, Guid.Empty);
- }
-
- // if we get to this point, then statistics exist and this must be the "end"
- // event, so we need to make sure the operation IDs match
- Assert.Equal(retrievedOperationId, beginOperationId);
- beginOperationId = Guid.Empty;
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteCommandError"))
- {
- operationHasError = true;
- Assert.NotNull(kvp.Value);
-
- SqlCommand sqlCommand = GetPropertyValueFromType(kvp.Value, "Command");
- Assert.NotNull(sqlCommand);
-
- Exception ex = GetPropertyValueFromType(kvp.Value, "Exception");
- Assert.NotNull(ex);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- if (sqlCommand.Connection.State == ConnectionState.Open)
- {
- Assert.NotEqual(connectionId, Guid.Empty);
- }
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionOpenBefore"))
- {
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionOpenAfter"))
- {
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- statistics = GetPropertyValueFromType(kvp.Value, "Statistics");
- Assert.NotNull(statistics);
-
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- Assert.NotEqual(connectionId, Guid.Empty);
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionOpenError"))
- {
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- Exception ex = GetPropertyValueFromType(kvp.Value, "Exception");
- Assert.NotNull(ex);
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionCloseBefore"))
- {
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- Assert.NotEqual(connectionId, Guid.Empty);
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionCloseAfter"))
- {
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
+ #endregion
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
+ #region Helpers
- statistics = GetPropertyValueFromType(kvp.Value, "Statistics");
-
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- Assert.NotEqual(connectionId, Guid.Empty);
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionCloseError"))
- {
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- Exception ex = GetPropertyValueFromType(kvp.Value, "Exception");
- Assert.NotNull(ex);
-
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- Assert.NotEqual(connectionId, Guid.Empty);
-
- statsLogged = true;
- }
- });
-
- diagnosticListenerObserver.Enable();
- using (DiagnosticListener.AllListeners.Subscribe(diagnosticListenerObserver))
+ private static void CollectStatisticsDiagnostics(
+ Action sqlOperation,
+ string[] expectedDiagnostics,
+ [CallerMemberName] string methodName = "")
+ {
+ bool statsLogged = false;
+ FakeDiagnosticListenerObserver observer = new(kvp =>
{
+ ValidateDiagnosticPayload(kvp);
+ statsLogged = true;
+ });
- Console.WriteLine(string.Format("Test: {0} Enabled Listeners", methodName));
-
- using (var server = new TdsServer(new DiagnosticsQueryEngine(), new TdsServerArguments()))
+ observer.Enable();
+ using (DiagnosticListener.AllListeners.Subscribe(observer))
+ using (var server = new TdsServer(new DiagnosticsQueryEngine(), new TdsServerArguments()))
+ {
+ server.Start(methodName);
+ string connectionString = new SqlConnectionStringBuilder
{
- server.Start(methodName);
- Console.WriteLine(string.Format("Test: {0} Started Server", methodName));
-
- var connectionString = new SqlConnectionStringBuilder
- {
- DataSource = $"localhost,{server.EndPoint.Port}",
- Encrypt = SqlConnectionEncryptOption.Optional
- }.ConnectionString;
-
- sqlOperation(connectionString);
+ DataSource = $"localhost,{server.EndPoint.Port}",
+ Encrypt = SqlConnectionEncryptOption.Optional
+ }.ConnectionString;
- Console.WriteLine(string.Format("Test: {0} SqlOperation Successful", methodName));
+ sqlOperation(connectionString);
- Assert.True(statsLogged);
+ Assert.True(statsLogged, "Expected at least one diagnostic event");
+ observer.Disable();
- diagnosticListenerObserver.Disable();
- foreach (string expected in expectedDiagnostics)
- {
- Assert.True(diagnosticListenerObserver.HasReceivedDiagnostic(expected), $"Missing diagnostic '{expected}'");
- }
-
- Console.WriteLine(string.Format("Test: {0} Listeners Disabled", methodName));
+ foreach (string expected in expectedDiagnostics)
+ {
+ Assert.True(observer.HasReceivedDiagnostic(expected), $"Missing diagnostic '{expected}'");
}
- Console.WriteLine(string.Format("Test: {0} Server Disposed", methodName));
}
- Console.WriteLine(string.Format("Test: {0} Listeners Disposed Successfully", methodName));
}
- private static async Task CollectStatisticsDiagnosticsAsync(Func sqlOperation, string[] expectedDiagnostics, [CallerMemberName] string methodName = "")
+ private static async Task CollectStatisticsDiagnosticsAsync(
+ Func sqlOperation,
+ string[] expectedDiagnostics,
+ [CallerMemberName] string methodName = "")
{
bool statsLogged = false;
- bool operationHasError = false;
- Guid beginOperationId = Guid.Empty;
-
- FakeDiagnosticListenerObserver diagnosticListenerObserver = new FakeDiagnosticListenerObserver(kvp =>
+ FakeDiagnosticListenerObserver observer = new(kvp =>
{
- IDictionary statistics;
-
- if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteCommandBefore"))
- {
- Assert.NotNull(kvp.Value);
-
- Guid retrievedOperationId = GetPropertyValueFromType(kvp.Value, "OperationId");
- Assert.NotEqual(retrievedOperationId, Guid.Empty);
-
- SqlCommand sqlCommand = GetPropertyValueFromType(kvp.Value, "Command");
- Assert.NotNull(sqlCommand);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- beginOperationId = retrievedOperationId;
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteCommandAfter"))
- {
- Assert.NotNull(kvp.Value);
-
- Guid retrievedOperationId = GetPropertyValueFromType(kvp.Value, "OperationId");
- Assert.NotEqual(retrievedOperationId, Guid.Empty);
-
- SqlCommand sqlCommand = GetPropertyValueFromType(kvp.Value, "Command");
- Assert.NotNull(sqlCommand);
-
- statistics = GetPropertyValueFromType(kvp.Value, "Statistics");
- if (!operationHasError)
- {
- Assert.NotNull(statistics);
- }
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- // if we get to this point, then statistics exist and this must be the "end"
- // event, so we need to make sure the operation IDs match
- Assert.Equal(retrievedOperationId, beginOperationId);
- beginOperationId = Guid.Empty;
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteCommandError"))
- {
- operationHasError = true;
- Assert.NotNull(kvp.Value);
-
- SqlCommand sqlCommand = GetPropertyValueFromType(kvp.Value, "Command");
- Assert.NotNull(sqlCommand);
-
- Exception ex = GetPropertyValueFromType(kvp.Value, "Exception");
- Assert.NotNull(ex);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionOpenBefore"))
- {
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionOpenAfter"))
- {
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- statistics = GetPropertyValueFromType(kvp.Value, "Statistics");
- Assert.NotNull(statistics);
-
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- if (sqlConnection.State == ConnectionState.Open)
- {
- Assert.NotEqual(connectionId, Guid.Empty);
- }
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionOpenError"))
- {
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- Exception ex = GetPropertyValueFromType(kvp.Value, "Exception");
- Assert.NotNull(ex);
+ ValidateDiagnosticPayload(kvp);
+ statsLogged = true;
+ });
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionCloseBefore"))
+ observer.Enable();
+ using (DiagnosticListener.AllListeners.Subscribe(observer))
+ using (var server = new TdsServer(new DiagnosticsQueryEngine(), new TdsServerArguments()))
+ {
+ server.Start(methodName);
+ string connectionString = new SqlConnectionStringBuilder
{
- Assert.NotNull(kvp.Value);
+ DataSource = $"localhost,{server.EndPoint.Port}",
+ Encrypt = SqlConnectionEncryptOption.Optional
+ }.ConnectionString;
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
+ await sqlOperation(connectionString);
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
+ Assert.True(statsLogged, "Expected at least one diagnostic event");
+ observer.Disable();
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- Assert.NotEqual(connectionId, Guid.Empty);
-
- statsLogged = true;
- }
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionCloseAfter"))
+ foreach (string expected in expectedDiagnostics)
{
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- statistics = GetPropertyValueFromType(kvp.Value, "Statistics");
-
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- Assert.NotEqual(connectionId, Guid.Empty);
-
- statsLogged = true;
+ Assert.True(observer.HasReceivedDiagnostic(expected), $"Missing diagnostic '{expected}'");
}
- else if (kvp.Key.Equals("Microsoft.Data.SqlClient.WriteConnectionCloseError"))
- {
- Assert.NotNull(kvp.Value);
-
- SqlConnection sqlConnection = GetPropertyValueFromType(kvp.Value, "Connection");
- Assert.NotNull(sqlConnection);
-
- string operation = GetPropertyValueFromType(kvp.Value, "Operation");
- Assert.False(string.IsNullOrWhiteSpace(operation));
-
- Exception ex = GetPropertyValueFromType(kvp.Value, "Exception");
- Assert.NotNull(ex);
-
- Guid connectionId = GetPropertyValueFromType(kvp.Value, "ConnectionId");
- Assert.NotEqual(connectionId, Guid.Empty);
+ }
+ }
- statsLogged = true;
- }
- });
+ private static void ValidateDiagnosticPayload(KeyValuePair kvp)
+ {
+ Assert.NotNull(kvp.Value);
- diagnosticListenerObserver.Enable();
- using (DiagnosticListener.AllListeners.Subscribe(diagnosticListenerObserver))
+ if (kvp.Key.Contains("Command"))
{
- Console.WriteLine(string.Format("Test: {0} Enabled Listeners", methodName));
- using (var server = new TdsServer(new DiagnosticsQueryEngine(), new TdsServerArguments()))
- {
- server.Start(methodName);
- Console.WriteLine(string.Format("Test: {0} Started Server", methodName));
-
- var connectionString = new SqlConnectionStringBuilder
- {
- DataSource = $"localhost,{server.EndPoint.Port}",
- Encrypt = SqlConnectionEncryptOption.Optional
- }.ConnectionString;
- await sqlOperation(connectionString);
-
- Console.WriteLine(string.Format("Test: {0} SqlOperation Successful", methodName));
-
- Assert.True(statsLogged);
-
- diagnosticListenerObserver.Disable();
- foreach (string expected in expectedDiagnostics)
- {
- Assert.True(diagnosticListenerObserver.HasReceivedDiagnostic(expected), $"Missing diagnostic '{expected}'");
- }
+ SqlCommand cmd = GetPropertyValueFromType(kvp.Value, "Command");
+ Assert.NotNull(cmd);
+ }
+ else if (kvp.Key.Contains("Connection"))
+ {
+ SqlConnection conn = GetPropertyValueFromType(kvp.Value, "Connection");
+ Assert.NotNull(conn);
+ }
- Console.WriteLine(string.Format("Test: {0} Listeners Disabled", methodName));
- }
- Console.WriteLine(string.Format("Test: {0} Server Disposed", methodName));
+ if (kvp.Key.Contains("Error"))
+ {
+ Exception ex = GetPropertyValueFromType(kvp.Value, "Exception");
+ Assert.NotNull(ex);
}
- Console.WriteLine(string.Format("Test: {0} Listeners Disposed Successfully", methodName));
+
+ string operation = GetPropertyValueFromType(kvp.Value, "Operation");
+ Assert.False(string.IsNullOrWhiteSpace(operation));
}
private static T GetPropertyValueFromType(object obj, string propName)
{
Type type = obj.GetType();
PropertyInfo pi = type.GetRuntimeProperty(propName);
-
- var propertyValue = pi.GetValue(obj);
- return (T)propertyValue;
+ return (T)pi.GetValue(obj);
}
+
+ #endregion
}
+ ///
+ /// Query engine that handles error queries (division by zero).
+ ///
public class DiagnosticsQueryEngine : QueryEngine
{
- public DiagnosticsQueryEngine() : base(new TdsServerArguments())
- {
- }
+ public DiagnosticsQueryEngine() : base(new TdsServerArguments()) { }
protected override TDSMessageCollection CreateQueryResponse(ITDSServerSession session, TDSSQLBatchToken batchRequest)
{
string lowerBatchText = batchRequest.Text.ToLowerInvariant();
-
- if (lowerBatchText.Contains("1 / 0")) // SELECT 1/0
+ if (lowerBatchText.Contains("1 / 0"))
{
- TDSErrorToken errorToken = new TDSErrorToken(8134, 1, 16, "Divide by zero error encountered.");
- TDSDoneToken doneToken = new TDSDoneToken(TDSDoneTokenStatusType.Final | TDSDoneTokenStatusType.Count, TDSDoneTokenCommandType.Select, 1);
- TDSMessage responseMessage = new TDSMessage(TDSMessageType.Response, errorToken, doneToken);
+ TDSErrorToken errorToken = new(8134, 1, 16, "Divide by zero error encountered.");
+ TDSDoneToken doneToken = new(TDSDoneTokenStatusType.Final | TDSDoneTokenStatusType.Count, TDSDoneTokenCommandType.Select, 1);
+ TDSMessage responseMessage = new(TDSMessageType.Response, errorToken, doneToken);
return new TDSMessageCollection(responseMessage);
}
- else
- {
- return base.CreateQueryResponse(session, batchRequest);
- }
+ return base.CreateQueryResponse(session, batchRequest);
}
}
}