From eadaf4b6a42da61a593e3987a05eb5a03190c6be Mon Sep 17 00:00:00 2001 From: Alex Hemsath <57361211+nr-ahemsath@users.noreply.github.com> Date: Mon, 27 Nov 2023 10:40:56 -0800 Subject: [PATCH] tests: consolidate sync and async variations of MsSql integration tests (#2095) * Consolidate MsSql sync/async tests * Remove unused test app * Consolidate async/sync query param tests * More consolidation --- .../MsSql/MicrosoftDataSqlClientExerciser.cs | 43 +- .../MsSql/MsSqlExerciserBase.cs | 21 + .../MsSql/SystemDataExerciser.cs | 43 +- .../MsSql/SystemDataSqlClientExerciser.cs | 45 +- .../BasicMvcCoreApplication.csproj | 21 - .../MicrosoftDataSqlClientController.cs | 236 ----------- .../Models/ErrorViewModel.cs | 15 - .../BasicMvcCoreApplication/Program.cs | 76 ---- .../Properties/launchSettings.json | 27 -- .../BasicMvcCoreApplication/Startup.cs | 48 --- .../appsettings.Development.json | 9 - .../BasicMvcCoreApplication/appsettings.json | 8 - .../UnboundedIntegrationTests.sln | 9 +- .../MsSql/MsSqlAsyncTests.cs | 282 ------------- .../MsSql/MsSqlQueryParamAsyncTests.cs | 389 ------------------ .../MsSql/MsSqlQueryParamTests.cs | 72 ++-- .../MsSql/MsSqlTests.cs | 156 +++++-- 17 files changed, 209 insertions(+), 1291 deletions(-) create mode 100644 tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/MsSqlExerciserBase.cs delete mode 100644 tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/BasicMvcCoreApplication.csproj delete mode 100644 tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Controllers/MicrosoftDataSqlClientController.cs delete mode 100644 tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Models/ErrorViewModel.cs delete mode 100644 tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Program.cs delete mode 100644 tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Properties/launchSettings.json delete mode 100644 tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Startup.cs delete mode 100644 tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/appsettings.Development.json delete mode 100644 tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/appsettings.json delete mode 100644 tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlAsyncTests.cs delete mode 100644 tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlQueryParamAsyncTests.cs diff --git a/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/MicrosoftDataSqlClientExerciser.cs b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/MicrosoftDataSqlClientExerciser.cs index e1ca7f1f29..d367d072f2 100644 --- a/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/MicrosoftDataSqlClientExerciser.cs +++ b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/MicrosoftDataSqlClientExerciser.cs @@ -1,4 +1,4 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. +// Copyright 2020 New Relic, Inc. All rights reserved. // SPDX-License-Identifier: Apache-2.0 using System.Collections.Generic; @@ -16,17 +16,9 @@ namespace MultiFunctionApplicationHelpers.NetStandardLibraries.MsSql { [Library] - public class MicrosoftDataSqlClientExerciser + public class MicrosoftDataSqlClientExerciser : MsSqlExerciserBase { - private const string InsertPersonMsSql = "INSERT INTO {0} (FirstName, LastName, Email) VALUES('Testy', 'McTesterson', 'testy@mctesterson.com')"; - private const string DeletePersonMsSql = "DELETE FROM {0} WHERE Email = 'testy@mctesterson.com'"; - private const string CountPersonMsSql = "SELECT COUNT(*) FROM {0} WITH(nolock)"; - private static readonly string CreateProcedureStatement = @"CREATE OR ALTER PROCEDURE [dbo].[{0}] {1} AS RETURN 0"; - private const string CreatePersonTableMsSql = "CREATE TABLE {0} (FirstName varchar(20) NOT NULL, LastName varchar(20) NOT NULL, Email varchar(50) NOT NULL)"; - private const string DropPersonTableMsSql = "IF (OBJECT_ID('{0}') IS NOT NULL) DROP TABLE {0}"; - private const string DropProcedureSql = "IF (OBJECT_ID('{0}') IS NOT NULL) DROP PROCEDURE {0}"; - [LibraryMethod] [Transaction] [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] @@ -38,7 +30,7 @@ public string MsSql(string tableName) { connection.Open(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = 'John'", connection)) + using (var command = new SqlCommand(SelectPersonByFirstNameMsSql, connection)) { using (var reader = command.ExecuteReader()) @@ -88,7 +80,7 @@ public async Task MsSqlAsync(string tableName) { await connection.OpenAsync(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = 'John'", connection)) + using (var command = new SqlCommand(SelectPersonByLastNameMsSql, connection)) { using (var reader = await command.ExecuteReaderAsync()) { @@ -137,7 +129,7 @@ public string MsSqlWithParameterizedQuery(bool paramsWithAtSign) { connection.Open(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN", connection)) + using (var command = new SqlCommand(SelectPersonByParameterizedFirstNameMsSql, connection)) { command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@FN" : "FN", "O'Keefe")); using (var reader = command.ExecuteReader()) @@ -160,7 +152,7 @@ public string MsSqlWithParameterizedQuery(bool paramsWithAtSign) [LibraryMethod] [Transaction] [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public async Task MsSqlAsync_WithParameterizedQuery(string tableName, bool paramsWithAtSign) + public async Task MsSqlAsync_WithParameterizedQuery(bool paramsWithAtSign) { var teamMembers = new List(); @@ -168,9 +160,9 @@ public async Task MsSqlAsync_WithParameterizedQuery(string tableName, bo { await connection.OpenAsync(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN", connection)) + using (var command = new SqlCommand(SelectPersonByParameterizedLastNameMsSql, connection)) { - command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@FN" : "FN", "O'Keefe")); + command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@LN" : "LN", "Lee")); using (var reader = await command.ExecuteReaderAsync()) { while (await reader.ReadAsync()) @@ -183,25 +175,6 @@ public async Task MsSqlAsync_WithParameterizedQuery(string tableName, bo } } } - - var insertSql = string.Format(InsertPersonMsSql, tableName); - var countSql = string.Format(CountPersonMsSql, tableName); - var deleteSql = string.Format(DeletePersonMsSql, tableName); - - using (var command = new SqlCommand(insertSql, connection)) - { - var insertCount = await command.ExecuteNonQueryAsync(); - } - - using (var command = new SqlCommand(countSql, connection)) - { - var teamMemberCount = await command.ExecuteScalarAsync(); - } - - using (var command = new SqlCommand(deleteSql, connection)) - { - var deleteCount = await command.ExecuteNonQueryAsync(); - } } return string.Join(",", teamMembers); diff --git a/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/MsSqlExerciserBase.cs b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/MsSqlExerciserBase.cs new file mode 100644 index 0000000000..96f91b9131 --- /dev/null +++ b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/MsSqlExerciserBase.cs @@ -0,0 +1,21 @@ +// Copyright 2020 New Relic, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +namespace MultiFunctionApplicationHelpers.NetStandardLibraries.MsSql +{ + public class MsSqlExerciserBase + { + + protected const string SelectPersonByFirstNameMsSql = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = 'John'"; + protected const string SelectPersonByLastNameMsSql = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE LastName = 'Doe'"; + protected const string SelectPersonByParameterizedFirstNameMsSql = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN"; + protected const string SelectPersonByParameterizedLastNameMsSql = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE LastName = @LN"; + protected const string InsertPersonMsSql = "INSERT INTO {0} (FirstName, LastName, Email) VALUES('Testy', 'McTesterson', 'testy@mctesterson.com')"; + protected const string DeletePersonMsSql = "DELETE FROM {0} WHERE Email = 'testy@mctesterson.com'"; + protected const string CountPersonMsSql = "SELECT COUNT(*) FROM {0} WITH(nolock)"; + protected static readonly string CreateProcedureStatement = @"CREATE OR ALTER PROCEDURE [dbo].[{0}] {1} AS RETURN 0"; + protected const string CreatePersonTableMsSql = "CREATE TABLE {0} (FirstName varchar(20) NOT NULL, LastName varchar(20) NOT NULL, Email varchar(50) NOT NULL)"; + protected const string DropPersonTableMsSql = "IF (OBJECT_ID('{0}') IS NOT NULL) DROP TABLE {0}"; + protected const string DropProcedureSql = "IF (OBJECT_ID('{0}') IS NOT NULL) DROP PROCEDURE {0}"; + } +} diff --git a/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/SystemDataExerciser.cs b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/SystemDataExerciser.cs index 33b821dc95..13aaf624e0 100644 --- a/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/SystemDataExerciser.cs +++ b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/SystemDataExerciser.cs @@ -1,4 +1,4 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. +// Copyright 2020 New Relic, Inc. All rights reserved. // SPDX-License-Identifier: Apache-2.0 #if NETFRAMEWORK @@ -19,16 +19,8 @@ namespace MultiFunctionApplicationHelpers.NetStandardLibraries.MsSql { [Library] - public class SystemDataExerciser + public class SystemDataExerciser : MsSqlExerciserBase { - private const string InsertPersonMsSql = "INSERT INTO {0} (FirstName, LastName, Email) VALUES('Testy', 'McTesterson', 'testy@mctesterson.com')"; - private const string DeletePersonMsSql = "DELETE FROM {0} WHERE Email = 'testy@mctesterson.com'"; - private const string CountPersonMsSql = "SELECT COUNT(*) FROM {0} WITH(nolock)"; - private static readonly string CreateProcedureStatement = @"CREATE OR ALTER PROCEDURE [dbo].[{0}] {1} AS RETURN 0"; - private const string CreatePersonTableMsSql = "CREATE TABLE {0} (FirstName varchar(20) NOT NULL, LastName varchar(20) NOT NULL, Email varchar(50) NOT NULL)"; - private const string DropPersonTableMsSql = "IF (OBJECT_ID('{0}') IS NOT NULL) DROP TABLE {0}"; - private const string DropProcedureSql = "IF (OBJECT_ID('{0}') IS NOT NULL) DROP PROCEDURE {0}"; - [LibraryMethod] [Transaction] [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] @@ -40,7 +32,7 @@ public string MsSql(string tableName) { connection.Open(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = 'John'", connection)) + using (var command = new SqlCommand(SelectPersonByFirstNameMsSql, connection)) { using (var reader = command.ExecuteReader()) @@ -90,7 +82,7 @@ public async Task MsSqlAsync(string tableName) { await connection.OpenAsync(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = 'John'", connection)) + using (var command = new SqlCommand(SelectPersonByLastNameMsSql, connection)) { using (var reader = await command.ExecuteReaderAsync()) { @@ -139,7 +131,7 @@ public string MsSqlWithParameterizedQuery(bool paramsWithAtSign) { connection.Open(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN", connection)) + using (var command = new SqlCommand(SelectPersonByParameterizedFirstNameMsSql, connection)) { command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@FN" : "FN", "O'Keefe")); using (var reader = command.ExecuteReader()) @@ -163,7 +155,7 @@ public string MsSqlWithParameterizedQuery(bool paramsWithAtSign) [LibraryMethod] [Transaction] [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public async Task MsSqlAsync_WithParameterizedQuery(string tableName, bool paramsWithAtSign) + public async Task MsSqlAsync_WithParameterizedQuery(bool paramsWithAtSign) { var teamMembers = new List(); @@ -171,9 +163,9 @@ public async Task MsSqlAsync_WithParameterizedQuery(string tableName, bo { await connection.OpenAsync(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN", connection)) + using (var command = new SqlCommand(SelectPersonByParameterizedLastNameMsSql, connection)) { - command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@FN" : "FN", "O'Keefe")); + command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@LN" : "LN", "Lee")); using (var reader = await command.ExecuteReaderAsync()) { while (await reader.ReadAsync()) @@ -186,25 +178,6 @@ public async Task MsSqlAsync_WithParameterizedQuery(string tableName, bo } } } - - var insertSql = string.Format(InsertPersonMsSql, tableName); - var countSql = string.Format(CountPersonMsSql, tableName); - var deleteSql = string.Format(DeletePersonMsSql, tableName); - - using (var command = new SqlCommand(insertSql, connection)) - { - var insertCount = await command.ExecuteNonQueryAsync(); - } - - using (var command = new SqlCommand(countSql, connection)) - { - var teamMemberCount = await command.ExecuteScalarAsync(); - } - - using (var command = new SqlCommand(deleteSql, connection)) - { - var deleteCount = await command.ExecuteNonQueryAsync(); - } } return string.Join(",", teamMembers); diff --git a/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/SystemDataSqlClientExerciser.cs b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/SystemDataSqlClientExerciser.cs index f36b527dca..bd8659bd0e 100644 --- a/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/SystemDataSqlClientExerciser.cs +++ b/tests/Agent/IntegrationTests/SharedApplications/Common/MultiFunctionApplicationHelpers/NetStandardLibraries/MsSql/SystemDataSqlClientExerciser.cs @@ -1,4 +1,4 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. +// Copyright 2020 New Relic, Inc. All rights reserved. // SPDX-License-Identifier: Apache-2.0 #if NETCOREAPP3_1_OR_GREATER @@ -13,22 +13,12 @@ using NewRelic.Agent.IntegrationTests.Shared.ReflectionHelpers; using NewRelic.Api.Agent; using System.Threading; -using System.Data.OleDb; -using System.Data.Odbc; namespace MultiFunctionApplicationHelpers.NetStandardLibraries.MsSql { [Library] - public class SystemDataSqlClientExerciser + public class SystemDataSqlClientExerciser : MsSqlExerciserBase { - private const string InsertPersonMsSql = "INSERT INTO {0} (FirstName, LastName, Email) VALUES('Testy', 'McTesterson', 'testy@mctesterson.com')"; - private const string DeletePersonMsSql = "DELETE FROM {0} WHERE Email = 'testy@mctesterson.com'"; - private const string CountPersonMsSql = "SELECT COUNT(*) FROM {0} WITH(nolock)"; - private static readonly string CreateProcedureStatement = @"CREATE OR ALTER PROCEDURE [dbo].[{0}] {1} AS RETURN 0"; - private const string CreatePersonTableMsSql = "CREATE TABLE {0} (FirstName varchar(20) NOT NULL, LastName varchar(20) NOT NULL, Email varchar(50) NOT NULL)"; - private const string DropPersonTableMsSql = "IF (OBJECT_ID('{0}') IS NOT NULL) DROP TABLE {0}"; - private const string DropProcedureSql = "IF (OBJECT_ID('{0}') IS NOT NULL) DROP PROCEDURE {0}"; - [LibraryMethod] [Transaction] [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] @@ -40,7 +30,7 @@ public string MsSql(string tableName) { connection.Open(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = 'John'", connection)) + using (var command = new SqlCommand(SelectPersonByFirstNameMsSql, connection)) { using (var reader = command.ExecuteReader()) @@ -90,7 +80,7 @@ public async Task MsSqlAsync(string tableName) { await connection.OpenAsync(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = 'John'", connection)) + using (var command = new SqlCommand(SelectPersonByLastNameMsSql, connection)) { using (var reader = await command.ExecuteReaderAsync()) { @@ -139,7 +129,7 @@ public string MsSqlWithParameterizedQuery(bool paramsWithAtSign) { connection.Open(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN", connection)) + using (var command = new SqlCommand(SelectPersonByParameterizedFirstNameMsSql, connection)) { command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@FN" : "FN", "O'Keefe")); using (var reader = command.ExecuteReader()) @@ -163,7 +153,7 @@ public string MsSqlWithParameterizedQuery(bool paramsWithAtSign) [LibraryMethod] [Transaction] [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] - public async Task MsSqlAsync_WithParameterizedQuery(string tableName, bool paramsWithAtSign) + public async Task MsSqlAsync_WithParameterizedQuery(bool paramsWithAtSign) { var teamMembers = new List(); @@ -171,9 +161,9 @@ public async Task MsSqlAsync_WithParameterizedQuery(string tableName, bo { await connection.OpenAsync(); - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN", connection)) + using (var command = new SqlCommand(SelectPersonByParameterizedLastNameMsSql, connection)) { - command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@FN" : "FN", "O'Keefe")); + command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@LN" : "LN", "Lee")); using (var reader = await command.ExecuteReaderAsync()) { while (await reader.ReadAsync()) @@ -186,25 +176,6 @@ public async Task MsSqlAsync_WithParameterizedQuery(string tableName, bo } } } - - var insertSql = string.Format(InsertPersonMsSql, tableName); - var countSql = string.Format(CountPersonMsSql, tableName); - var deleteSql = string.Format(DeletePersonMsSql, tableName); - - using (var command = new SqlCommand(insertSql, connection)) - { - var insertCount = await command.ExecuteNonQueryAsync(); - } - - using (var command = new SqlCommand(countSql, connection)) - { - var teamMemberCount = await command.ExecuteScalarAsync(); - } - - using (var command = new SqlCommand(deleteSql, connection)) - { - var deleteCount = await command.ExecuteNonQueryAsync(); - } } return string.Join(",", teamMembers); diff --git a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/BasicMvcCoreApplication.csproj b/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/BasicMvcCoreApplication.csproj deleted file mode 100644 index 649c68f701..0000000000 --- a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/BasicMvcCoreApplication.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - net7.0 - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - diff --git a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Controllers/MicrosoftDataSqlClientController.cs b/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Controllers/MicrosoftDataSqlClientController.cs deleted file mode 100644 index 6accd6a5d1..0000000000 --- a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Controllers/MicrosoftDataSqlClientController.cs +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - - -using NewRelic.Agent.IntegrationTests.Shared; -using System.Collections.Generic; -using System.Data; -using Microsoft.Data.SqlClient; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; - -namespace BasicMvcApplication.Controllers -{ - public class MicrosoftDataSqlClientController : Controller - { - private const string InsertPersonMsSql = "INSERT INTO {0} (FirstName, LastName, Email) VALUES('Testy', 'McTesterson', 'testy@mctesterson.com')"; - private const string DeletePersonMsSql = "DELETE FROM {0} WHERE Email = 'testy@mctesterson.com'"; - private const string CountPersonMsSql = "SELECT COUNT(*) FROM {0} WITH(nolock)"; - - [HttpGet] - [Route("MicrosoftDataSqlClient/MsSql")] - public string MsSql(string tableName) - { - var teamMembers = new List(); - - using (var connection = new SqlConnection(MsSqlConfiguration.MsSqlConnectionString)) - { - connection.Open(); - - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = 'John'", connection)) - { - - using (var reader = command.ExecuteReader()) - { - while (reader.Read()) - { - teamMembers.Add(reader.GetString(reader.GetOrdinal("FirstName"))); - if (reader.NextResult()) - { - teamMembers.Add(reader.GetString(reader.GetOrdinal("FirstName"))); - } - } - } - } - - var insertSql = string.Format(InsertPersonMsSql, tableName); - var countSql = string.Format(CountPersonMsSql, tableName); - var deleteSql = string.Format(DeletePersonMsSql, tableName); - - using (var command = new SqlCommand(insertSql, connection)) - { - var insertCount = command.ExecuteNonQuery(); - } - - using (var command = new SqlCommand(countSql, connection)) - { - var teamMemberCount = command.ExecuteScalar(); - } - - using (var command = new SqlCommand(deleteSql, connection)) - { - var deleteCount = command.ExecuteNonQuery(); - } - } - - return string.Join(",", teamMembers); - } - - [HttpGet] - [Route("MicrosoftDataSqlClient/MsSqlAsync")] - public async Task MsSqlAsync(string tableName) - { - var teamMembers = new List(); - - using (var connection = new SqlConnection(MsSqlConfiguration.MsSqlConnectionString)) - { - await connection.OpenAsync(); - - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = 'John'", connection)) - { - using (var reader = await command.ExecuteReaderAsync()) - { - while (await reader.ReadAsync()) - { - teamMembers.Add(reader.GetString(reader.GetOrdinal("FirstName"))); - if (await reader.NextResultAsync()) - { - teamMembers.Add(reader.GetString(reader.GetOrdinal("FirstName"))); - } - } - } - } - - var insertSql = string.Format(InsertPersonMsSql, tableName); - var countSql = string.Format(CountPersonMsSql, tableName); - var deleteSql = string.Format(DeletePersonMsSql, tableName); - - using (var command = new SqlCommand(insertSql, connection)) - { - var insertCount = await command.ExecuteNonQueryAsync(); - } - - using (var command = new SqlCommand(countSql, connection)) - { - var teamMemberCount = await command.ExecuteScalarAsync(); - } - - using (var command = new SqlCommand(deleteSql, connection)) - { - var deleteCount = await command.ExecuteNonQueryAsync(); - } - } - - return string.Join(",", teamMembers); - } - - [HttpGet] - [Route("MicrosoftDataSqlClient/MsSqlWithParameterizedQuery")] - public string MsSqlWithParameterizedQuery(string tableName, bool paramsWithAtSign) - { - var teamMembers = new List(); - - using (var connection = new SqlConnection(MsSqlConfiguration.MsSqlConnectionString)) - { - connection.Open(); - - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN", connection)) - { - command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@FN" : "FN", "O'Keefe")); - using (var reader = command.ExecuteReader()) - { - while (reader.Read()) - { - teamMembers.Add(reader.GetString(reader.GetOrdinal("FirstName"))); - if (reader.NextResult()) - { - teamMembers.Add(reader.GetString(reader.GetOrdinal("FirstName"))); - } - } - } - } - } - - return string.Join(",", teamMembers); - } - - [HttpGet] - [Route("MicrosoftDataSqlClient/MsSqlAsync_WithParameterizedQuery")] - public async Task MsSqlAsync_WithParameterizedQuery(string tableName, bool paramsWithAtSign) - { - var teamMembers = new List(); - - using (var connection = new SqlConnection(MsSqlConfiguration.MsSqlConnectionString)) - { - await connection.OpenAsync(); - - using (var command = new SqlCommand("SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN", connection)) - { - command.Parameters.Add(new SqlParameter(paramsWithAtSign ? "@FN" : "FN", "O'Keefe")); - using (var reader = await command.ExecuteReaderAsync()) - { - while (await reader.ReadAsync()) - { - teamMembers.Add(reader.GetString(reader.GetOrdinal("FirstName"))); - if (await reader.NextResultAsync()) - { - teamMembers.Add(reader.GetString(reader.GetOrdinal("FirstName"))); - } - } - } - } - - var insertSql = string.Format(InsertPersonMsSql, tableName); - var countSql = string.Format(CountPersonMsSql, tableName); - var deleteSql = string.Format(DeletePersonMsSql, tableName); - - using (var command = new SqlCommand(insertSql, connection)) - { - var insertCount = await command.ExecuteNonQueryAsync(); - } - - using (var command = new SqlCommand(countSql, connection)) - { - var teamMemberCount = await command.ExecuteScalarAsync(); - } - - using (var command = new SqlCommand(deleteSql, connection)) - { - var deleteCount = await command.ExecuteNonQueryAsync(); - } - } - - return string.Join(",", teamMembers); - } - - [HttpGet] - [Route("MicrosoftDataSqlClient/MsSqlParameterizedStoredProcedure")] - public int MsSqlParameterizedStoredProcedure(string procedureName, bool paramsWithAtSign) - { - EnsureProcedure(procedureName, DbParameterData.MsSqlParameters); - - using (var connection = new SqlConnection(MsSqlConfiguration.MsSqlConnectionString)) - using (var command = new SqlCommand(procedureName, connection)) - { - connection.Open(); - command.CommandType = CommandType.StoredProcedure; - foreach (var parameter in DbParameterData.MsSqlParameters) - { - var paramName = paramsWithAtSign - ? parameter.ParameterName - : parameter.ParameterName.TrimStart('@'); - - command.Parameters.Add(new SqlParameter(paramName, parameter.Value)); - } - - return command.ExecuteNonQuery(); - } - } - - private static readonly string CreateProcedureStatement = @"CREATE OR ALTER PROCEDURE [dbo].[{0}] {1} AS RETURN 0"; - - private void EnsureProcedure(string procedureName, DbParameter[] dbParameters) - { - var parameters = string.Join(", ", dbParameters.Select(x => $"{x.ParameterName} {x.DbTypeName}")); - var statement = string.Format(CreateProcedureStatement, procedureName, parameters); - using (var connection = new SqlConnection(MsSqlConfiguration.MsSqlConnectionString)) - using (var command = new SqlCommand(statement, connection)) - { - connection.Open(); - command.ExecuteNonQuery(); - } - } - - } -} diff --git a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Models/ErrorViewModel.cs b/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Models/ErrorViewModel.cs deleted file mode 100644 index 5deeea54f6..0000000000 --- a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Models/ErrorViewModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - - -using System; - -namespace BasicMvcCoreApplication.Models -{ - public class ErrorViewModel - { - public string RequestId { get; set; } - - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - } -} diff --git a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Program.cs b/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Program.cs deleted file mode 100644 index 8410078f2d..0000000000 --- a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Program.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - - -using System; -using System.IO; -using System.Linq; -using System.Diagnostics; -using System.Reflection; -using System.Threading; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.CodeAnalysis; - - -namespace BasicMvcCoreApplication -{ - public class Program - { - private const string DefaultPort = "5001"; - - private static string _port; - - private static string _applicationName; - - public static void Main(string[] args) - { - var commandLine = string.Join(" ", args); - - _applicationName = Path.GetFileNameWithoutExtension(new Uri(Assembly.GetExecutingAssembly().Location).LocalPath) + ".exe"; - - Console.WriteLine($"[{_applicationName}] Joined args: {commandLine}"); - - var result = CommandLineParser.SplitCommandLineIntoArguments(commandLine, true); - - var argPort = result.FirstOrDefault()?.Split('=')[1]; - _port = argPort ?? DefaultPort; - - Console.WriteLine($"[{_applicationName}] Received port: {argPort} | Using port: {_port}"); - - var ct = new CancellationTokenSource(); - var task = BuildWebHost(args).RunAsync(ct.Token); - - using (var eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, - "app_server_wait_for_all_request_done_" + _port)) - { - CreatePidFile(); - eventWaitHandle.WaitOne(TimeSpan.FromMinutes(5)); - } - - ct.Cancel(); - - task.GetAwaiter().GetResult(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .UseUrls($@"http://localhost:{_port}/") - .Build(); - - private static void CreatePidFile() - { - var pid = Process.GetCurrentProcess().Id; - var applicationDirectory = - Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().Location).LocalPath), - _applicationName); - var pidFilePath = applicationDirectory + ".pid"; - - using (var file = File.CreateText(pidFilePath)) - { - file.WriteLine(pid); - } - } - } -} diff --git a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Properties/launchSettings.json b/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Properties/launchSettings.json deleted file mode 100644 index a08c687261..0000000000 --- a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Properties/launchSettings.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:60383", - "sslPort": 0 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "BasicMvcCoreApplication": { - "commandName": "Project", - "launchBrowser": true, - "applicationUrl": "http://localhost:5000", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} \ No newline at end of file diff --git a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Startup.cs b/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Startup.cs deleted file mode 100644 index b2989ffd95..0000000000 --- a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/Startup.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -namespace BasicMvcCoreApplication -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddMvc(options => - { - options.SuppressAsyncSuffixInActionNames = false; - }); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - app.UseStaticFiles(); - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - } - } -} diff --git a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/appsettings.Development.json b/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/appsettings.Development.json deleted file mode 100644 index e203e9407e..0000000000 --- a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/appsettings.Development.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Microsoft": "Information" - } - } -} diff --git a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/appsettings.json b/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/appsettings.json deleted file mode 100644 index def9159a7d..0000000000 --- a/tests/Agent/IntegrationTests/UnboundedApplications/BasicMvcCoreApplication/appsettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/tests/Agent/IntegrationTests/UnboundedIntegrationTests.sln b/tests/Agent/IntegrationTests/UnboundedIntegrationTests.sln index 56769744a5..04d81af6f1 100644 --- a/tests/Agent/IntegrationTests/UnboundedIntegrationTests.sln +++ b/tests/Agent/IntegrationTests/UnboundedIntegrationTests.sln @@ -23,8 +23,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MongoDBApplication", "Unbou EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NewRelic.Testing.Assertions", "..\NewRelic.Testing.Assertions\NewRelic.Testing.Assertions.csproj", "{2A932B62-8787-4963-8D53-F83BF6ACBB5C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicMvcCoreApplication", "UnboundedApplications\BasicMvcCoreApplication\BasicMvcCoreApplication.csproj", "{26AEFF66-DFF2-4C85-AB0C-0B2672E8A434}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SharedApplications", "SharedApplications", "{859E490D-4C1A-4D9D-8271-5FE2E0726ADE}" ProjectSection(SolutionItems) = preProject SharedApplications\WcfAppIisHosted\WcfAppIisHosted.csproj = SharedApplications\WcfAppIisHosted\WcfAppIisHosted.csproj @@ -80,10 +78,6 @@ Global {2A932B62-8787-4963-8D53-F83BF6ACBB5C}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A932B62-8787-4963-8D53-F83BF6ACBB5C}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A932B62-8787-4963-8D53-F83BF6ACBB5C}.Release|Any CPU.Build.0 = Release|Any CPU - {26AEFF66-DFF2-4C85-AB0C-0B2672E8A434}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {26AEFF66-DFF2-4C85-AB0C-0B2672E8A434}.Debug|Any CPU.Build.0 = Debug|Any CPU - {26AEFF66-DFF2-4C85-AB0C-0B2672E8A434}.Release|Any CPU.ActiveCfg = Release|Any CPU - {26AEFF66-DFF2-4C85-AB0C-0B2672E8A434}.Release|Any CPU.Build.0 = Release|Any CPU {8D07A4F7-70FD-40D4-AA95-BA9A98F14CD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8D07A4F7-70FD-40D4-AA95-BA9A98F14CD0}.Debug|Any CPU.Build.0 = Debug|Any CPU {8D07A4F7-70FD-40D4-AA95-BA9A98F14CD0}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -119,7 +113,6 @@ Global GlobalSection(NestedProjects) = preSolution {EA98CDD2-655D-4239-9B9F-44EB806DEE53} = {03BAC949-FAD7-4EE6-A2BD-45E3DE2407F9} {A8308E64-6659-4EFB-A9C4-0C48D4C99A61} = {03BAC949-FAD7-4EE6-A2BD-45E3DE2407F9} - {26AEFF66-DFF2-4C85-AB0C-0B2672E8A434} = {03BAC949-FAD7-4EE6-A2BD-45E3DE2407F9} {8D07A4F7-70FD-40D4-AA95-BA9A98F14CD0} = {859E490D-4C1A-4D9D-8271-5FE2E0726ADE} {5350D3F3-CE09-4992-9756-ACCC92A9129C} = {859E490D-4C1A-4D9D-8271-5FE2E0726ADE} {129FF113-1F3A-4DAA-8D6F-287DF67A68FA} = {859E490D-4C1A-4D9D-8271-5FE2E0726ADE} @@ -128,7 +121,7 @@ Global {F35861EC-9861-4776-AF51-9C2B7F1DBA5C} = {129FF113-1F3A-4DAA-8D6F-287DF67A68FA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.Common.6.0.1304.0\lib\NET45;packages\EnterpriseLibrary.Data.6.0.1304.0\lib\NET45 SolutionGuid = {656848E2-BFD2-4092-9328-C6CDF39B1274} + EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.Common.6.0.1304.0\lib\NET45;packages\EnterpriseLibrary.Data.6.0.1304.0\lib\NET45 EndGlobalSection EndGlobal diff --git a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlAsyncTests.cs b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlAsyncTests.cs deleted file mode 100644 index 88c59571b3..0000000000 --- a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlAsyncTests.cs +++ /dev/null @@ -1,282 +0,0 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - - -using System; -using System.Collections.Generic; -using System.Linq; -using NewRelic.Agent.IntegrationTestHelpers; -using NewRelic.Agent.IntegrationTestHelpers.Models; -using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures; -using NewRelic.Agent.IntegrationTests.Shared; -using NewRelic.Testing.Assertions; -using Xunit; -using Xunit.Abstractions; - -namespace NewRelic.Agent.UnboundedIntegrationTests.MsSql -{ - public abstract class MsSqlAsyncTestsBase : NewRelicIntegrationTest - where TFixture : ConsoleDynamicMethodFixture - { - private readonly ConsoleDynamicMethodFixture _fixture; - private readonly string _expectedTransactionName; - - private readonly string _tableName; - private readonly string _libraryName; - - public MsSqlAsyncTestsBase(TFixture fixture, ITestOutputHelper output, string excerciserName, string libraryName) : base(fixture) - { - MsSqlWarmupHelper.WarmupMsSql(); - - _fixture = fixture; - _fixture.TestLogger = output; - _expectedTransactionName = $"OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.MsSql.{excerciserName}/MsSqlAsync"; - _tableName = Utilities.GenerateTableName(); - _libraryName = libraryName; - - _fixture.AddCommand($"{excerciserName} CreateTable {_tableName}"); - _fixture.AddCommand($"{excerciserName} MsSqlAsync {_tableName}"); - _fixture.AddCommand($"{excerciserName} Wait 5000"); - _fixture.AddCommand($"{excerciserName} DropTable {_tableName}"); - - _fixture.AddActions - ( - setupConfiguration: () => - { - var configPath = fixture.DestinationNewRelicConfigFilePath; - var configModifier = new NewRelicConfigModifier(configPath); - configModifier.ConfigureFasterMetricsHarvestCycle(15); - configModifier.ConfigureFasterTransactionTracesHarvestCycle(15); - configModifier.ConfigureFasterSqlTracesHarvestCycle(15); - - configModifier.ForceTransactionTraces(); - - CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(configPath, new[] { "configuration", "transactionTracer" }, "explainEnabled", "true"); - CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(configPath, new[] { "configuration", "transactionTracer" }, "explainThreshold", "1"); - - var instrumentationFilePath = $@"{fixture.DestinationNewRelicExtensionsDirectoryPath}\NewRelic.Providers.Wrapper.Sql.Instrumentation.xml"; - CommonUtils.SetAttributeOnTracerFactoryInNewRelicInstrumentation( - instrumentationFilePath, - "", "enabled", "true"); - }, - exerciseApplication: () => - { - _fixture.AgentLog.WaitForLogLine(AgentLogBase.AgentConnectedLogLineRegex, TimeSpan.FromMinutes(1)); - _fixture.AgentLog.WaitForLogLine(AgentLogBase.SqlTraceDataLogLineRegex, TimeSpan.FromMinutes(1)); - } - ); - - _fixture.Initialize(); - } - - [Fact] - public void Test() - { - var expectedDatastoreCallCount = 4; - - //This value is dictated by the query and subsequent ExecuteScalarAsync that is being run as part of this test. In this case, we're running a query that returns a single row. - //This results in a call to ReadAsync followed by a NextResultAsync and finally another ReadAsync. Therefore - //the call count for the Iterate metric should be 3. - var expectedIterateCallCount = 3; - - var expectedMetrics = new List - { - new Assertions.ExpectedMetric { metricName = @"Datastore/all", callCount = expectedDatastoreCallCount }, - new Assertions.ExpectedMetric { metricName = @"Datastore/MSSQL/all", callCount = expectedDatastoreCallCount }, - new Assertions.ExpectedMetric { metricName = @"Datastore/allOther", callCount = expectedDatastoreCallCount }, - - new Assertions.ExpectedMetric { metricName = $"DotNet/{_libraryName}.SqlConnection/OpenAsync", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = @"Datastore/MSSQL/allOther", callCount = expectedDatastoreCallCount }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/instance/MSSQL/{CommonUtils.NormalizeHostname(MsSqlConfiguration.MsSqlServer)}/default", callCount = expectedDatastoreCallCount}, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", callCount = 2 }, - new Assertions.ExpectedMetric { metricName = @"Datastore/statement/MSSQL/teammembers/select", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = @"Datastore/statement/MSSQL/teammembers/select", callCount = 1, metricScope = _expectedTransactionName}, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/select", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/select", callCount = 1, metricScope = _expectedTransactionName}, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/insert", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/insert", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/insert", callCount = 1, metricScope = _expectedTransactionName}, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/delete", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/delete", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/delete", callCount = 1, metricScope = _expectedTransactionName}, - new Assertions.ExpectedMetric { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount }, - new Assertions.ExpectedMetric { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount, metricScope = _expectedTransactionName} - }; - - var unexpectedMetrics = new List - { - // The operation metric should not be scoped because the statement metric is scoped instead - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", callCount = 3, metricScope = _expectedTransactionName }, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/insert", callCount = 1, metricScope = _expectedTransactionName }, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/delete", callCount = 1, metricScope = _expectedTransactionName }, - - // Don't double count the open - new Assertions.ExpectedMetric { metricName = $"DotNet/{_libraryName}.SqlConnection/Open" }, - }; - var expectedTransactionTraceSegments = new List - { - "Datastore/statement/MSSQL/teammembers/select" - }; - var expectedTransactionTraceSegmentParameters = new List - { - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "explain_plan"}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "sql", parameterValue = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = ?"}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "host", parameterValue = CommonUtils.NormalizeHostname(MsSqlConfiguration.MsSqlServer)}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "port_path_or_id", parameterValue = "default"}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "database_name", parameterValue = "NewRelic"} - - }; - - var expectedTransactionEventIntrinsicAttributes = new List - { - "databaseDuration" - }; - var expectedSqlTraces = new List - { - new Assertions.ExpectedSqlTrace - { - TransactionName = _expectedTransactionName, - Sql = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = ?", - DatastoreMetricName = "Datastore/statement/MSSQL/teammembers/select", - HasExplainPlan = true - }, - new Assertions.ExpectedSqlTrace - { - TransactionName = _expectedTransactionName, - Sql = $"SELECT COUNT(*) FROM {_tableName} WITH(nolock)", - DatastoreMetricName = $"Datastore/statement/MSSQL/{_tableName}/select", - - HasExplainPlan = true - }, - new Assertions.ExpectedSqlTrace - { - TransactionName = _expectedTransactionName, - Sql = $"INSERT INTO {_tableName} (FirstName, LastName, Email) VALUES(?, ?, ?)", - DatastoreMetricName = $"Datastore/statement/MSSQL/{_tableName}/insert", - - HasExplainPlan = true - }, - new Assertions.ExpectedSqlTrace - { - TransactionName = _expectedTransactionName, - Sql = $"DELETE FROM {_tableName} WHERE Email = ?", - DatastoreMetricName = $"Datastore/statement/MSSQL/{_tableName}/delete", - - HasExplainPlan = true - } - }; - - var metrics = _fixture.AgentLog.GetMetrics().ToList(); - var transactionSample = _fixture.AgentLog.TryGetTransactionSample(_expectedTransactionName); - var transactionEvent = _fixture.AgentLog.TryGetTransactionEvent(_expectedTransactionName); - var sqlTraces = _fixture.AgentLog.GetSqlTraces().ToList(); - - NrAssert.Multiple( - () => Assert.NotNull(transactionSample), - () => Assert.NotNull(transactionEvent) - ); - - NrAssert.Multiple - ( - () => Assertions.MetricsExist(expectedMetrics, metrics), - () => Assertions.MetricsDoNotExist(unexpectedMetrics, metrics), - () => Assertions.TransactionTraceSegmentsExist(expectedTransactionTraceSegments, transactionSample), - () => Assertions.TransactionTraceSegmentParametersExist(expectedTransactionTraceSegmentParameters, transactionSample), - () => Assertions.TransactionEventHasAttributes(expectedTransactionEventIntrinsicAttributes, TransactionEventAttributeType.Intrinsic, transactionEvent), - () => Assertions.SqlTraceExists(expectedSqlTraces, sqlTraces) - ); - } - } - - [NetFrameworkTest] - public class MsSqlAsyncTests_SystemData_FWLatest : MsSqlAsyncTestsBase - { - public MsSqlAsyncTests_SystemData_FWLatest(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "SystemDataExerciser", - libraryName: "System.Data.SqlClient") - { - } - } - - [NetCoreTest] - public class MsSqlAsyncTests_SystemDataSqlClient_CoreLatest : MsSqlAsyncTestsBase - { - public MsSqlAsyncTests_SystemDataSqlClient_CoreLatest(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "SystemDataSqlClientExerciser", - libraryName: "System.Data.SqlClient") - { - } - } - - [NetCoreTest] - public class MsSqlAsyncTests_SystemDataSqlClient_CoreOldest : MsSqlAsyncTestsBase - { - public MsSqlAsyncTests_SystemDataSqlClient_CoreOldest(ConsoleDynamicMethodFixtureCoreOldest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "SystemDataSqlClientExerciser", - libraryName: "System.Data.SqlClient") - { - } - } - - [NetFrameworkTest] - public class MsSqlAsyncTests_MicrosoftDataSqlClient_FWLatest : MsSqlAsyncTestsBase - { - public MsSqlAsyncTests_MicrosoftDataSqlClient_FWLatest(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - libraryName: "Microsoft.Data.SqlClient") - { - } - } - - [NetFrameworkTest] - public class MsSqlAsyncTests_MicrosoftDataSqlClient_FW462 : MsSqlAsyncTestsBase - { - public MsSqlAsyncTests_MicrosoftDataSqlClient_FW462(ConsoleDynamicMethodFixtureFW462 fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - libraryName: "Microsoft.Data.SqlClient") - { - } - } - - - [NetCoreTest] - public class MsSqlAsyncTests_MicrosoftDataSqlClient_CoreLatest : MsSqlAsyncTestsBase - { - public MsSqlAsyncTests_MicrosoftDataSqlClient_CoreLatest(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - libraryName: "Microsoft.Data.SqlClient") - { - } - } - - [NetCoreTest] - public class MsSqlAsyncTests_MicrosoftDataSqlClient_CoreOldest : MsSqlAsyncTestsBase - { - public MsSqlAsyncTests_MicrosoftDataSqlClient_CoreOldest(ConsoleDynamicMethodFixtureCoreOldest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - libraryName: "Microsoft.Data.SqlClient") - { - } - } -} diff --git a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlQueryParamAsyncTests.cs b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlQueryParamAsyncTests.cs deleted file mode 100644 index b179ec0bea..0000000000 --- a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlQueryParamAsyncTests.cs +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright 2020 New Relic, Inc. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - - -using System; -using System.Collections.Generic; -using System.Linq; -using NewRelic.Agent.IntegrationTestHelpers; -using NewRelic.Agent.IntegrationTestHelpers.Models; -using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures; -using NewRelic.Agent.IntegrationTests.Shared; -using NewRelic.Testing.Assertions; -using Xunit; -using Xunit.Abstractions; - -namespace NewRelic.Agent.UnboundedIntegrationTests.MsSql -{ - public abstract class MsSqlQueryParamAsyncTestsBase : NewRelicIntegrationTest - where TFixture : ConsoleDynamicMethodFixture - { - private readonly ConsoleDynamicMethodFixture _fixture; - private readonly string _expectedTransactionName; - private readonly string _tableName; - private readonly bool _paramsWithAtSign; - - public MsSqlQueryParamAsyncTestsBase(TFixture fixture, ITestOutputHelper output, string excerciserName, bool paramsWithAtSign) : base(fixture) - { - MsSqlWarmupHelper.WarmupMsSql(); - - _fixture = fixture; - _fixture.TestLogger = output; - _expectedTransactionName = $"OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.MsSql.{excerciserName}/MsSqlAsync_WithParameterizedQuery"; - _tableName = Utilities.GenerateTableName(); - - _fixture.AddCommand($"{excerciserName} CreateTable {_tableName}"); - _fixture.AddCommand($"{excerciserName} MsSqlAsync_WithParameterizedQuery {_tableName} {paramsWithAtSign}"); - _fixture.AddCommand($"{excerciserName} Wait 5000"); - _fixture.AddCommand($"{excerciserName} DropTable {_tableName}"); - - _paramsWithAtSign = paramsWithAtSign; - - _fixture.AddActions - ( - setupConfiguration: () => - { - var configPath = fixture.DestinationNewRelicConfigFilePath; - var configModifier = new NewRelicConfigModifier(configPath); - configModifier.ConfigureFasterMetricsHarvestCycle(15); - configModifier.ConfigureFasterTransactionTracesHarvestCycle(15); - configModifier.ConfigureFasterSqlTracesHarvestCycle(15); - - configModifier.ForceTransactionTraces(); - configModifier.SetLogLevel("finest"); //This has to stay at finest to ensure parameter check security - - CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(configPath, new[] { "configuration", "transactionTracer" }, "explainEnabled", "true"); - CommonUtils.ModifyOrCreateXmlAttributeInNewRelicConfig(configPath, new[] { "configuration", "transactionTracer" }, "explainThreshold", "1"); - - var instrumentationFilePath = $@"{fixture.DestinationNewRelicExtensionsDirectoryPath}\NewRelic.Providers.Wrapper.Sql.Instrumentation.xml"; - CommonUtils.SetAttributeOnTracerFactoryInNewRelicInstrumentation( - instrumentationFilePath, - "", "enabled", "true"); - }, - exerciseApplication: () => - { - _fixture.AgentLog.WaitForLogLine(AgentLogBase.AgentConnectedLogLineRegex, TimeSpan.FromMinutes(1)); - _fixture.AgentLog.WaitForLogLine(AgentLogBase.SqlTraceDataLogLineRegex, TimeSpan.FromMinutes(1)); - } - ); - - _fixture.Initialize(); - } - - [Fact] - public void Test() - { - var expectedDatastoreCallCount = 4; - //This value is dictated by the query and subsequent ExecuteScalarAsync that is being run as part of this test. In this case, we're running a query that returns - //a single row. - //This results in a call to ReadAsync followed by a NextResultAsync and finally a another ReadAsync. Therefore the call count for the Iterate metric should be 4. - var expectedIterateCallCount = 3; - - var expectedMetrics = new List - { - new Assertions.ExpectedMetric { metricName = @"Datastore/all", callCount = expectedDatastoreCallCount }, - new Assertions.ExpectedMetric { metricName = @"Datastore/MSSQL/all", callCount = expectedDatastoreCallCount }, - new Assertions.ExpectedMetric { metricName = @"Datastore/allOther", callCount = expectedDatastoreCallCount }, - new Assertions.ExpectedMetric { metricName = @"Datastore/MSSQL/allOther", callCount = expectedDatastoreCallCount }, - - new Assertions.ExpectedMetric { metricName = $@"Datastore/instance/MSSQL/{CommonUtils.NormalizeHostname(MsSqlConfiguration.MsSqlServer)}/default", callCount = expectedDatastoreCallCount}, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", callCount = 2 }, - new Assertions.ExpectedMetric { metricName = @"Datastore/statement/MSSQL/teammembers/select", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = @"Datastore/statement/MSSQL/teammembers/select", callCount = 1, metricScope = _expectedTransactionName}, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/select", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/select", callCount = 1, metricScope = _expectedTransactionName}, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/insert", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/insert", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/insert", callCount = 1, metricScope = _expectedTransactionName}, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/delete", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/delete", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/delete", callCount = 1, metricScope = _expectedTransactionName}, - - new Assertions.ExpectedMetric { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount }, - new Assertions.ExpectedMetric { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount, metricScope = _expectedTransactionName} - }; - - var unexpectedMetrics = new List - { - // The operation metric should not be scoped because the statement metric is scoped instead - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", callCount = 3, metricScope = _expectedTransactionName }, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/insert", callCount = 1, metricScope = _expectedTransactionName }, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/delete", callCount = 1, metricScope = _expectedTransactionName } - }; - var expectedTransactionTraceSegments = new List - { - "Datastore/statement/MSSQL/teammembers/select" - }; - var expectedTransactionTraceSegmentParameters = new List - { - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "explain_plan"}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "sql", parameterValue = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN"}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "host", parameterValue = CommonUtils.NormalizeHostname(MsSqlConfiguration.MsSqlServer)}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "port_path_or_id", parameterValue = "default"}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "database_name", parameterValue = "NewRelic"} - }; - - var expectedTransactionEventIntrinsicAttributes = new List - { - "databaseDuration" - }; - - var expectedSqlTraces = new List - { - new Assertions.ExpectedSqlTrace - { - TransactionName = _expectedTransactionName, - Sql = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN", - DatastoreMetricName = "Datastore/statement/MSSQL/teammembers/select", - HasExplainPlan = true - }, - new Assertions.ExpectedSqlTrace - { - TransactionName = _expectedTransactionName, - Sql = $"SELECT COUNT(*) FROM {_tableName} WITH(nolock)", - DatastoreMetricName = $"Datastore/statement/MSSQL/{_tableName}/select", - - HasExplainPlan = true - }, - new Assertions.ExpectedSqlTrace - { - TransactionName =_expectedTransactionName, - Sql = $"INSERT INTO {_tableName} (FirstName, LastName, Email) VALUES(?, ?, ?)", - DatastoreMetricName = $"Datastore/statement/MSSQL/{_tableName}/insert", - - HasExplainPlan = true - }, - new Assertions.ExpectedSqlTrace - { - TransactionName = _expectedTransactionName, - Sql = $"DELETE FROM {_tableName} WHERE Email = ?", - DatastoreMetricName = $"Datastore/statement/MSSQL/{_tableName}/delete", - - HasExplainPlan = true - } - }; - - var expectedQueryParameters = _paramsWithAtSign - ? DbParameterData.MsSqlParameters.ToDictionary(p => p.ParameterName, p => p.ExpectedValue) - : DbParameterData.MsSqlParameters.ToDictionary(p => p.ParameterName.TrimStart('@'), p => p.ExpectedValue); - - var metrics = _fixture.AgentLog.GetMetrics().ToList(); - var transactionSample = _fixture.AgentLog.TryGetTransactionSample(_expectedTransactionName); - var transactionEvent = _fixture.AgentLog.TryGetTransactionEvent(_expectedTransactionName); - var sqlTraces = _fixture.AgentLog.GetSqlTraces().ToList(); - var logEntries = _fixture.AgentLog.GetFileLines().ToList(); - - NrAssert.Multiple( - () => Assert.NotNull(transactionSample), - () => Assert.NotNull(transactionEvent) - ); - - NrAssert.Multiple - ( - () => Assertions.MetricsExist(expectedMetrics, metrics), - () => Assertions.MetricsDoNotExist(unexpectedMetrics, metrics), - () => Assertions.TransactionTraceSegmentsExist(expectedTransactionTraceSegments, transactionSample), - () => Assertions.TransactionTraceSegmentParametersExist(expectedTransactionTraceSegmentParameters, transactionSample), - () => Assertions.TransactionEventHasAttributes(expectedTransactionEventIntrinsicAttributes, TransactionEventAttributeType.Intrinsic, transactionEvent), - () => Assertions.SqlTraceExists(expectedSqlTraces, sqlTraces), - () => Assertions.LogLinesNotExist(new[] { AgentLogFile.ErrorLogLinePrefixRegex }, logEntries) - ); - } - } - - - #region System.Data (.NET Framework only) - [NetFrameworkTest] - public class MsSqlQueryParamAsyncTests_SystemData_FWLatest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_SystemData_FWLatest(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "SystemDataExerciser", - paramsWithAtSign: true) - { - } - } - - [NetFrameworkTest] - public class MsSqlQueryParamAsyncTests_SystemData_NoAtSigns_FWLatest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_SystemData_NoAtSigns_FWLatest(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "SystemDataExerciser", - paramsWithAtSign: false) - { - } - } - #endregion - - - #region System.Data.SqlClient (.NET Core/5+ only) - - [NetCoreTest] - public class MsSqlQueryParamAsyncTests_SystemDataSqlClient_CoreLatest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_SystemDataSqlClient_CoreLatest(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "SystemDataSqlClientExerciser", - paramsWithAtSign: true) - { - } - } - - [NetCoreTest] - public class MsSqlQueryParamAsyncTests_SystemDataSqlClient_NoAtSigns_CoreLatest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_SystemDataSqlClient_NoAtSigns_CoreLatest(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "SystemDataSqlClientExerciser", - paramsWithAtSign: false) - { - } - } - - [NetCoreTest] - public class MsSqlQueryParamAsyncTests_SystemDataSqlClient_CoreOldest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_SystemDataSqlClient_CoreOldest(ConsoleDynamicMethodFixtureCoreOldest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "SystemDataSqlClientExerciser", - paramsWithAtSign: true) - { - } - } - - [NetCoreTest] - public class MsSqlQueryParamAsyncTests_SystemDataSqlClient_NoAtSigns_CoreOldest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_SystemDataSqlClient_NoAtSigns_CoreOldest(ConsoleDynamicMethodFixtureCoreOldest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "SystemDataSqlClientExerciser", - paramsWithAtSign: false) - { - } - } - #endregion - - - #region Microsoft.Data.SqlClient (FW and Core/5+) - - [NetFrameworkTest] - public class MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_FWLatest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_FWLatest(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) - - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - paramsWithAtSign: true) - { - } - } - - [NetFrameworkTest] - public class MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_NoAtSigns_FWLatest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_NoAtSigns_FWLatest(ConsoleDynamicMethodFixtureFWLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - paramsWithAtSign: false) - { - } - } - - [NetFrameworkTest] - public class MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_FW462 : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_FW462(ConsoleDynamicMethodFixtureFW462 fixture, ITestOutputHelper output) - - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - paramsWithAtSign: true) - { - } - } - - [NetFrameworkTest] - public class MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_NoAtSigns_FW462 : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_NoAtSigns_FW462(ConsoleDynamicMethodFixtureFW462 fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - paramsWithAtSign: false) - { - } - } - - [NetCoreTest] - public class MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_CoreLatest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_CoreLatest(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - paramsWithAtSign: true) - { - } - } - - [NetCoreTest] - public class MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_NoAtSigns_CoreLatest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_NoAtSigns_CoreLatest(ConsoleDynamicMethodFixtureCoreLatest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - paramsWithAtSign: false) - { - } - } - - [NetCoreTest] - public class MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_CoreOldest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_CoreOldest(ConsoleDynamicMethodFixtureCoreOldest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - paramsWithAtSign: true) - { - } - } - - [NetCoreTest] - public class MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_NoAtSigns_CoreOldest : MsSqlQueryParamAsyncTestsBase - { - public MsSqlQueryParamAsyncTests_MicrosoftDataSqlClient_NoAtSigns_CoreOldest(ConsoleDynamicMethodFixtureCoreOldest fixture, ITestOutputHelper output) - : base( - fixture: fixture, - output: output, - excerciserName: "MicrosoftDataSqlClientExerciser", - paramsWithAtSign: false) - { - } - } - - #endregion -} diff --git a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlQueryParamTests.cs b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlQueryParamTests.cs index f76c43ee46..0b9fade440 100644 --- a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlQueryParamTests.cs +++ b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlQueryParamTests.cs @@ -20,7 +20,7 @@ public abstract class MsSqlQueryParamTestsBase : NewRelicIntegrationTe { private readonly ConsoleDynamicMethodFixture _fixture; private readonly string _expectedTransactionName; - private readonly string _tableName; + private readonly string _expectedAsyncTransactionName; private readonly bool _paramsWithAtSigns; public MsSqlQueryParamTestsBase(TFixture fixture, ITestOutputHelper output, string excerciserName, bool paramsWithAtSign) : base(fixture) @@ -30,11 +30,10 @@ public MsSqlQueryParamTestsBase(TFixture fixture, ITestOutputHelper output, stri _fixture = fixture; _fixture.TestLogger = output; _expectedTransactionName = $"OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.MsSql.{excerciserName}/MsSqlWithParameterizedQuery"; - _tableName = Utilities.GenerateTableName(); + _expectedAsyncTransactionName = $"OtherTransaction/Custom/MultiFunctionApplicationHelpers.NetStandardLibraries.MsSql.{excerciserName}/MsSqlAsync_WithParameterizedQuery"; - _fixture.AddCommand($"{excerciserName} CreateTable {_tableName}"); _fixture.AddCommand($"{excerciserName} MsSqlWithParameterizedQuery {paramsWithAtSign}"); - _fixture.AddCommand($"{excerciserName} DropTable {_tableName}"); + _fixture.AddCommand($"{excerciserName} MsSqlAsync_WithParameterizedQuery {paramsWithAtSign}"); _paramsWithAtSigns = paramsWithAtSign; @@ -75,20 +74,23 @@ public void Test() { var expectedMetrics = new List { - new Assertions.ExpectedMetric { metricName = @"Datastore/all", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = @"Datastore/allOther", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = @"Datastore/MSSQL/all", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = @"Datastore/MSSQL/allOther", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/instance/MSSQL/{CommonUtils.NormalizeHostname(MsSqlConfiguration.MsSqlServer)}/default", callCount = 1}, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/teammembers/select", callCount = 1 }, + new Assertions.ExpectedMetric { metricName = @"Datastore/all", callCount = 2 }, + new Assertions.ExpectedMetric { metricName = @"Datastore/allOther", callCount = 2 }, + new Assertions.ExpectedMetric { metricName = @"Datastore/MSSQL/all", callCount = 2 }, + new Assertions.ExpectedMetric { metricName = @"Datastore/MSSQL/allOther", callCount = 2 }, + new Assertions.ExpectedMetric { metricName = $@"Datastore/instance/MSSQL/{CommonUtils.NormalizeHostname(MsSqlConfiguration.MsSqlServer)}/default", callCount = 2}, + new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", callCount = 2 }, + new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/teammembers/select", callCount = 2 }, new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/teammembers/select", callCount = 1, metricScope = _expectedTransactionName}, + new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/teammembers/select", callCount = 1, metricScope = _expectedAsyncTransactionName}, }; var unexpectedMetrics = new List { - // The operation metric should not be scoped because the statement metric is scoped instead - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", metricScope = _expectedTransactionName }, + // The operation metric should not be scoped because the statement metric is scoped instead + new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", metricScope = _expectedTransactionName }, + new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", metricScope = _expectedAsyncTransactionName }, }; + var expectedTransactionTraceSegments = new List { $"Datastore/statement/MSSQL/teammembers/select" @@ -98,18 +100,12 @@ public void Test() var expectedQueryParameters = _paramsWithAtSigns ? new Dictionary { { "@FN", "O'Keefe" } } : new Dictionary { { "FN", "O'Keefe" } }; - - - var expectedTransactionTraceSegmentParameters = new List - { - new Assertions.ExpectedSegmentParameter { segmentName = $"Datastore/statement/MSSQL/teammembers/select", parameterName = "explain_plan" }, - new Assertions.ExpectedSegmentParameter { segmentName = $"Datastore/statement/MSSQL/teammembers/select", parameterName = "sql", parameterValue = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = @FN"}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "host", parameterValue = CommonUtils.NormalizeHostname(MsSqlConfiguration.MsSqlServer)}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "port_path_or_id", parameterValue = "default"}, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "database_name", parameterValue = "NewRelic"}, - }; + var expectedAsyncQueryParameters = _paramsWithAtSigns + ? new Dictionary { { "@LN", "Lee" } } + : new Dictionary { { "LN", "Lee" } }; var expectedTransactionTraceQueryParameters = new Assertions.ExpectedSegmentQueryParameters { segmentName = $"Datastore/statement/MSSQL/teammembers/select", QueryParameters = expectedQueryParameters }; + var expectedAsyncTransactionTraceQueryParameters = new Assertions.ExpectedSegmentQueryParameters { segmentName = $"Datastore/statement/MSSQL/teammembers/select", QueryParameters = expectedAsyncQueryParameters }; var expectedTransactionEventIntrinsicAttributes = new List { @@ -126,17 +122,41 @@ public void Test() QueryParameters = expectedQueryParameters, HasExplainPlan = true }, + new Assertions.ExpectedSqlTrace + { + TransactionName = _expectedAsyncTransactionName, + Sql = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE LastName = @LN", + DatastoreMetricName = "Datastore/statement/MSSQL/teammembers/select", + QueryParameters = expectedAsyncQueryParameters, + HasExplainPlan = true + }, }; var metrics = _fixture.AgentLog.GetMetrics().ToList(); - var transactionSample = _fixture.AgentLog.TryGetTransactionSample(_expectedTransactionName); + var syncTransactionSample = _fixture.AgentLog.TryGetTransactionSample(_expectedTransactionName); + var asyncTransactionSample = _fixture.AgentLog.TryGetTransactionSample(_expectedAsyncTransactionName); var transactionEvent = _fixture.AgentLog.TryGetTransactionEvent(_expectedTransactionName); + var asyncTransactionEvent = _fixture.AgentLog.TryGetTransactionEvent(_expectedAsyncTransactionName); var sqlTraces = _fixture.AgentLog.GetSqlTraces().ToList(); var logEntries = _fixture.AgentLog.GetFileLines(); + // some variable expectations based on which transaction was sampled + var asyncSampled = asyncTransactionSample != null; + var transactionSample = asyncSampled ? asyncTransactionSample : syncTransactionSample; + var whereClause = asyncSampled ? "LastName = @LN" : "FirstName = @FN"; + var expectedTransactionTraceSegmentParameters = new List + { + new Assertions.ExpectedSegmentParameter { segmentName = $"Datastore/statement/MSSQL/teammembers/select", parameterName = "explain_plan" }, + new Assertions.ExpectedSegmentParameter { segmentName = $"Datastore/statement/MSSQL/teammembers/select", parameterName = "sql", parameterValue = $"SELECT * FROM NewRelic.dbo.TeamMembers WHERE {whereClause}"}, + new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "host", parameterValue = CommonUtils.NormalizeHostname(MsSqlConfiguration.MsSqlServer)}, + new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "port_path_or_id", parameterValue = "default"}, + new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "database_name", parameterValue = "NewRelic"}, + }; + NrAssert.Multiple( () => Assert.NotNull(transactionSample), - () => Assert.NotNull(transactionEvent) + () => Assert.NotNull(transactionEvent), + () => Assert.NotNull(asyncTransactionEvent) ); NrAssert.Multiple @@ -146,7 +166,7 @@ public void Test() () => Assertions.TransactionTraceSegmentsExist(expectedTransactionTraceSegments, transactionSample), () => Assertions.TransactionTraceSegmentParametersExist(expectedTransactionTraceSegmentParameters, transactionSample), - () => Assertions.TransactionTraceSegmentQueryParametersExist(expectedTransactionTraceQueryParameters, transactionSample), + () => Assertions.TransactionTraceSegmentQueryParametersExist(asyncSampled ? expectedAsyncTransactionTraceQueryParameters: expectedTransactionTraceQueryParameters, transactionSample), () => Assertions.TransactionEventHasAttributes(expectedTransactionEventIntrinsicAttributes, TransactionEventAttributeType.Intrinsic, transactionEvent), () => Assertions.SqlTraceExists(expectedSqlTraces, sqlTraces), diff --git a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlTests.cs b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlTests.cs index 5cc5de23b1..6fa4aa0b60 100644 --- a/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlTests.cs +++ b/tests/Agent/IntegrationTests/UnboundedIntegrationTests/MsSql/MsSqlTests.cs @@ -20,20 +20,33 @@ public abstract class MsSqlTestsBase : NewRelicIntegrationTest { + _fixture.AgentLog.WaitForLogLine(AgentLogBase.AgentConnectedLogLineRegex, TimeSpan.FromMinutes(1)); _fixture.AgentLog.WaitForLogLine(AgentLogBase.SqlTraceDataLogLineRegex, TimeSpan.FromMinutes(1)); } ); @@ -64,10 +78,10 @@ public MsSqlTestsBase(TFixture fixture, ITestOutputHelper output, string excerci [Fact] public void Test() { - var expectedDatastoreCallCount = 4; - //This value is dictated by the query that is being run as part of this test. In this case, we're running a query that returns a single row. - //This results in a call to Read, NextResult and then a final Read. Therefore the call count for the Iterate metric should be 3. - var expectedIterateCallCount = 3; + var expectedDatastoreCallCount = 8; + //This value is dictated by the queries that are being run as part of this test. In this case, we're running two queries that each return a single row. + //This results in a call to Read, NextResult and then a final Read. Therefore the overall call count for the Iterate metric should be 6. + var expectedIterateCallCount = 6; var expectedMetrics = new List { @@ -75,53 +89,81 @@ public void Test() new Assertions.ExpectedMetric { metricName = @"Datastore/allOther", callCount = expectedDatastoreCallCount }, new Assertions.ExpectedMetric { metricName = @"Datastore/MSSQL/all", callCount = expectedDatastoreCallCount }, new Assertions.ExpectedMetric { metricName = @"Datastore/MSSQL/allOther", callCount = expectedDatastoreCallCount }, + + new Assertions.ExpectedMetric { metricName = $"DotNet/{_libraryName}.SqlConnection/Open", callCount = 1 }, + new Assertions.ExpectedMetric { metricName = $"DotNet/{_libraryName}.SqlConnection/OpenAsync", callCount = 1 }, + new Assertions.ExpectedMetric { metricName = $@"Datastore/instance/MSSQL/{CommonUtils.NormalizeHostname(MsSqlConfiguration.MsSqlServer)}/default", callCount = expectedDatastoreCallCount}, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", callCount = 2 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/teammembers/select", callCount = 1 }, - new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/teammembers/select", callCount = 1, metricScope = _expectedTransactionName}, + new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", callCount = 4 }, + new Assertions.ExpectedMetric { metricName = @"Datastore/statement/MSSQL/teammembers/select", callCount = 2 }, + new Assertions.ExpectedMetric { metricName = @"Datastore/statement/MSSQL/teammembers/select", callCount = 1, metricScope = _expectedTransactionName}, + new Assertions.ExpectedMetric { metricName = @"Datastore/statement/MSSQL/teammembers/select", callCount = 1, metricScope = _expectedAsyncTransactionName}, new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/select", callCount = 1 }, new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/select", callCount = 1, metricScope = _expectedTransactionName}, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/insert", callCount = 1 }, + new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_asyncTableName}/select", callCount = 1 }, + new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_asyncTableName}/select", callCount = 1, metricScope = _expectedAsyncTransactionName}, + new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/insert", callCount = 2 }, new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/insert", callCount = 1 }, new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/insert", callCount = 1, metricScope = _expectedTransactionName}, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/delete", callCount = 1 }, + new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_asyncTableName}/insert", callCount = 1 }, + new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_asyncTableName}/insert", callCount = 1, metricScope = _expectedAsyncTransactionName}, + new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/delete", callCount = 2 }, new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/delete", callCount = 1 }, new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_tableName}/delete", callCount = 1, metricScope = _expectedTransactionName}, + new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_asyncTableName}/delete", callCount = 1 }, + new Assertions.ExpectedMetric { metricName = $@"Datastore/statement/MSSQL/{_asyncTableName}/delete", callCount = 1, metricScope = _expectedAsyncTransactionName}, new Assertions.ExpectedMetric { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount }, - new Assertions.ExpectedMetric { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount, metricScope = _expectedTransactionName} + new Assertions.ExpectedMetric { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount / 2, metricScope = _expectedTransactionName}, + new Assertions.ExpectedMetric { metricName = @"DotNet/DatabaseResult/Iterate", callCount = expectedIterateCallCount / 2, metricScope = _expectedAsyncTransactionName} }; var unexpectedMetrics = new List { // The operation metric should not be scoped because the statement metric is scoped instead new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", metricScope = _expectedTransactionName }, new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/insert", metricScope = _expectedTransactionName }, - new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/delete", metricScope = _expectedTransactionName } + new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/delete", metricScope = _expectedTransactionName }, + new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/select", metricScope = _expectedAsyncTransactionName }, + new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/insert", metricScope = _expectedAsyncTransactionName }, + new Assertions.ExpectedMetric { metricName = @"Datastore/operation/MSSQL/delete", metricScope = _expectedAsyncTransactionName } }; var expectedTransactionTraceSegments = new List { - $"Datastore/statement/MSSQL/teammembers/select" + "Datastore/statement/MSSQL/teammembers/select" }; + var expectedTransactionEventIntrinsicAttributes = new List + { + "databaseDuration" + }; + + var metrics = _fixture.AgentLog.GetMetrics().ToList(); + var syncTransactionSample = _fixture.AgentLog.TryGetTransactionSample(_expectedTransactionName); + var syncTransactionEvent = _fixture.AgentLog.TryGetTransactionEvent(_expectedTransactionName); + var asyncTransactionSample = _fixture.AgentLog.TryGetTransactionSample(_expectedAsyncTransactionName); + var asyncTransactionEvent = _fixture.AgentLog.TryGetTransactionEvent(_expectedAsyncTransactionName); + var sqlTraces = _fixture.AgentLog.GetSqlTraces().ToList(); + + // Some variable expectations based on which transaction was sampled + var sampledTransactionSample = syncTransactionSample != null ? syncTransactionSample : asyncTransactionSample; + var firstOrLastNameQueried = syncTransactionSample != null ? "FirstName" : "LastName"; + var expectedTransactionTraceSegmentParameters = new List { new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "explain_plan" }, - new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "sql", parameterValue = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = ?"}, + new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "sql", parameterValue = $"SELECT * FROM NewRelic.dbo.TeamMembers WHERE {firstOrLastNameQueried} = ?"}, new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "host", parameterValue = CommonUtils.NormalizeHostname(MsSqlConfiguration.MsSqlServer)}, new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "port_path_or_id", parameterValue = "default"}, new Assertions.ExpectedSegmentParameter { segmentName = "Datastore/statement/MSSQL/teammembers/select", parameterName = "database_name", parameterValue = "NewRelic"} }; - var expectedTransactionEventIntrinsicAttributes = new List - { - "databaseDuration" - }; + // There should be a total of 8 traces: 4 for the sync methods and 4 for the async methods. var expectedSqlTraces = new List { new Assertions.ExpectedSqlTrace { - TransactionName = _expectedTransactionName, + TransactionName = _expectedTransactionName, //sync select Sql = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE FirstName = ?", DatastoreMetricName = "Datastore/statement/MSSQL/teammembers/select", @@ -129,7 +171,15 @@ public void Test() }, new Assertions.ExpectedSqlTrace { - TransactionName = _expectedTransactionName, + TransactionName = _expectedAsyncTransactionName, //async select - note querying LastName + Sql = "SELECT * FROM NewRelic.dbo.TeamMembers WHERE LastName = ?", + DatastoreMetricName = "Datastore/statement/MSSQL/teammembers/select", + + HasExplainPlan = true + }, + new Assertions.ExpectedSqlTrace + { + TransactionName = _expectedTransactionName, //sync count Sql = $"SELECT COUNT(*) FROM {_tableName} WITH(nolock)", DatastoreMetricName = $"Datastore/statement/MSSQL/{_tableName}/select", @@ -137,7 +187,15 @@ public void Test() }, new Assertions.ExpectedSqlTrace { - TransactionName = _expectedTransactionName, + TransactionName = _expectedAsyncTransactionName, //async count + Sql = $"SELECT COUNT(*) FROM {_asyncTableName} WITH(nolock)", + DatastoreMetricName = $"Datastore/statement/MSSQL/{_asyncTableName}/select", + + HasExplainPlan = true + }, + new Assertions.ExpectedSqlTrace + { + TransactionName = _expectedTransactionName, //sync insert Sql = $"INSERT INTO {_tableName} (FirstName, LastName, Email) VALUES(?, ?, ?)", DatastoreMetricName = $"Datastore/statement/MSSQL/{_tableName}/insert", @@ -145,33 +203,46 @@ public void Test() }, new Assertions.ExpectedSqlTrace { - TransactionName = _expectedTransactionName, + TransactionName = _expectedAsyncTransactionName, //async insert + Sql = $"INSERT INTO {_asyncTableName} (FirstName, LastName, Email) VALUES(?, ?, ?)", + DatastoreMetricName = $"Datastore/statement/MSSQL/{_asyncTableName}/insert", + + HasExplainPlan = true + }, + new Assertions.ExpectedSqlTrace + { + TransactionName = _expectedTransactionName, //sync delete Sql = $"DELETE FROM {_tableName} WHERE Email = ?", DatastoreMetricName = $"Datastore/statement/MSSQL/{_tableName}/delete", + HasExplainPlan = true + }, + new Assertions.ExpectedSqlTrace + { + TransactionName = _expectedAsyncTransactionName, //async delete + Sql = $"DELETE FROM {_asyncTableName} WHERE Email = ?", + DatastoreMetricName = $"Datastore/statement/MSSQL/{_asyncTableName}/delete", + HasExplainPlan = true } }; - var metrics = _fixture.AgentLog.GetMetrics().ToList(); - var transactionSample = _fixture.AgentLog.TryGetTransactionSample(_expectedTransactionName); - var transactionEvent = _fixture.AgentLog.TryGetTransactionEvent(_expectedTransactionName); - var sqlTraces = _fixture.AgentLog.GetSqlTraces().ToList(); - NrAssert.Multiple( - () => Assert.NotNull(transactionSample), - () => Assert.NotNull(transactionEvent) + () => Assert.NotNull(sampledTransactionSample), + () => Assert.NotNull(syncTransactionEvent), + () => Assert.NotNull(asyncTransactionEvent) ); NrAssert.Multiple ( () => Assertions.MetricsExist(expectedMetrics, metrics), () => Assertions.MetricsDoNotExist(unexpectedMetrics, metrics), - () => Assertions.TransactionTraceSegmentsExist(expectedTransactionTraceSegments, transactionSample), + () => Assertions.TransactionTraceSegmentsExist(expectedTransactionTraceSegments, sampledTransactionSample), - () => Assertions.TransactionTraceSegmentParametersExist(expectedTransactionTraceSegmentParameters, transactionSample), + () => Assertions.TransactionTraceSegmentParametersExist(expectedTransactionTraceSegmentParameters, sampledTransactionSample), - () => Assertions.TransactionEventHasAttributes(expectedTransactionEventIntrinsicAttributes, TransactionEventAttributeType.Intrinsic, transactionEvent), + () => Assertions.TransactionEventHasAttributes(expectedTransactionEventIntrinsicAttributes, TransactionEventAttributeType.Intrinsic, syncTransactionEvent), + () => Assertions.TransactionEventHasAttributes(expectedTransactionEventIntrinsicAttributes, TransactionEventAttributeType.Intrinsic, asyncTransactionEvent), () => Assertions.SqlTraceExists(expectedSqlTraces, sqlTraces) ); } @@ -184,7 +255,8 @@ public MsSqlTests_SystemData_FWLatest(ConsoleDynamicMethodFixtureFWLatest fixtur : base( fixture: fixture, output: output, - excerciserName: "SystemDataExerciser") + excerciserName: "SystemDataExerciser", + libraryName: "System.Data.SqlClient") { } } @@ -196,7 +268,8 @@ public MsSqlTests_SystemDataSqlClient_CoreLatest(ConsoleDynamicMethodFixtureCore : base( fixture: fixture, output: output, - excerciserName: "SystemDataSqlClientExerciser") + excerciserName: "SystemDataSqlClientExerciser", + libraryName: "System.Data.SqlClient") { } } @@ -208,7 +281,8 @@ public MsSqlTests_SystemDataSqlClient_CoreOldest(ConsoleDynamicMethodFixtureCore : base( fixture: fixture, output: output, - excerciserName: "SystemDataSqlClientExerciser") + excerciserName: "SystemDataSqlClientExerciser", + libraryName: "System.Data.SqlClient") { } } @@ -220,7 +294,8 @@ public MsSqlTests_MicrosoftDataSqlClient_FWLatest(ConsoleDynamicMethodFixtureFWL : base( fixture: fixture, output: output, - excerciserName: "MicrosoftDataSqlClientExerciser") + excerciserName: "MicrosoftDataSqlClientExerciser", + libraryName: "Microsoft.Data.SqlClient") { } } @@ -232,7 +307,8 @@ public MsSqlTests_MicrosoftDataSqlClient_FW462(ConsoleDynamicMethodFixtureFW462 : base( fixture: fixture, output: output, - excerciserName: "MicrosoftDataSqlClientExerciser") + excerciserName: "MicrosoftDataSqlClientExerciser", + libraryName: "Microsoft.Data.SqlClient") { } } @@ -244,7 +320,8 @@ public MsSqlTests_MicrosoftDataSqlClient_CoreLatest(ConsoleDynamicMethodFixtureC : base( fixture: fixture, output: output, - excerciserName: "MicrosoftDataSqlClientExerciser") + excerciserName: "MicrosoftDataSqlClientExerciser", + libraryName: "Microsoft.Data.SqlClient") { } } @@ -256,7 +333,8 @@ public MsSqlTests_MicrosoftDataSqlClient_CoreOldest(ConsoleDynamicMethodFixtureC : base( fixture: fixture, output: output, - excerciserName: "MicrosoftDataSqlClientExerciser") + excerciserName: "MicrosoftDataSqlClientExerciser", + libraryName: "Microsoft.Data.SqlClient") { } }