diff --git a/src/Microsoft.Data.SqlClient/tests/Common/Fixtures/AzureKeyVaultKeyFixtureBase.cs b/src/Microsoft.Data.SqlClient/tests/Common/Fixtures/AzureKeyVaultKeyFixtureBase.cs index f70560be9e..2836156b65 100644 --- a/src/Microsoft.Data.SqlClient/tests/Common/Fixtures/AzureKeyVaultKeyFixtureBase.cs +++ b/src/Microsoft.Data.SqlClient/tests/Common/Fixtures/AzureKeyVaultKeyFixtureBase.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Security.Cryptography; using Azure.Core; using Azure.Security.KeyVault.Keys; @@ -20,20 +21,41 @@ namespace Microsoft.Data.SqlClient.Tests.Common.Fixtures; public abstract class AzureKeyVaultKeyFixtureBase : IDisposable { private readonly KeyClient _keyClient; - private readonly Random _randomGenerator; + private readonly RandomNumberGenerator _randomGenerator; private readonly List _createdKeys = new List(); protected AzureKeyVaultKeyFixtureBase(Uri keyVaultUri, TokenCredential keyVaultToken) { _keyClient = new KeyClient(keyVaultUri, keyVaultToken); - _randomGenerator = new Random(); + _randomGenerator = RandomNumberGenerator.Create(); } protected Uri CreateKey(string name, int keySize) { - CreateRsaKeyOptions createOptions = new CreateRsaKeyOptions(GenerateUniqueName(name)) { KeySize = keySize }; - KeyVaultKey created = _keyClient.CreateRsaKey(createOptions); + const int MaxConflictResolutions = 5; + KeyVaultKey created; + int i = 0; + + while (true) + { + CreateRsaKeyOptions createOptions = new CreateRsaKeyOptions(GenerateUniqueName(name)) { KeySize = keySize }; + + try + { + created = _keyClient.CreateRsaKey(createOptions); + break; + } + // It's possible for a key to already exist with the same name, even in a deleted state. If so, CreateRsaKey + // will throw an exception with HTTP status code 409 (Conflict.) + // We can't assume we possess permissions to purge or to recover the key, so regenerate the name and try again. + // Only make MaxConflictResolutions attempts, to avoid possible infinite loops. + catch (Azure.RequestFailedException conflictException) + when (conflictException.Status == 409 && i < MaxConflictResolutions) + { + i++; + } + } _createdKeys.Add(created); return created.Id; @@ -43,7 +65,7 @@ private string GenerateUniqueName(string name) { byte[] rndBytes = new byte[16]; - _randomGenerator.NextBytes(rndBytes); + _randomGenerator.GetBytes(rndBytes); return name + "-" + BitConverter.ToString(rndBytes); } @@ -66,5 +88,7 @@ protected virtual void Dispose(bool disposing) continue; } } + + _randomGenerator.Dispose(); } } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Batch/BatchTests.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Batch/BatchTests.cs index 991d55cdeb..7c843ad889 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Batch/BatchTests.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/Batch/BatchTests.cs @@ -7,6 +7,7 @@ using System.Data; using System.Data.Common; using System.Threading.Tasks; +using Microsoft.Data.SqlClient.Tests.Common.Fixtures.DatabaseObjects; using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests @@ -377,9 +378,13 @@ public static void ExceptionWithoutBatchContainsNoBatch() [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] public static void ParameterInOutAndReturn() { - string create = - @" -CREATE PROCEDURE TestInAndOutParams + SqlParameter input = CreateParameter("@Input", SqlDbType.Int, 2); + SqlParameter inputOutput = CreateParameter("@InOut", SqlDbType.Int, 4, ParameterDirection.InputOutput); + SqlParameter output = CreateParameter("@Output", SqlDbType.Int, DBNull.Value, ParameterDirection.Output); + SqlParameter returned = CreateParameter("@RETURN_VALUE", SqlDbType.Int, DBNull.Value, ParameterDirection.ReturnValue); + + using (SqlConnection conn = new(DataTestUtility.TCPConnectionString)) + using (StoredProcedure spTestInAndOutParams = new(conn, "TestInAndOutParams", @" @Input int, @InOut int OUTPUT, @Output int = default OUTPUT @@ -388,26 +393,14 @@ CREATE PROCEDURE TestInAndOutParams SET NOCOUNT ON; SELECT @InOut = 2 * @InOut, @Output = 2 * @Input RETURN @Input -END"; - string drop = "DROP PROCEDURE TestInAndOutParams"; - - SqlParameter input = CreateParameter("@Input", SqlDbType.Int, 2); - SqlParameter inputOutput = CreateParameter("@InOut", SqlDbType.Int, 4, ParameterDirection.InputOutput); - SqlParameter output = CreateParameter("@Output", SqlDbType.Int, DBNull.Value, ParameterDirection.Output); - SqlParameter returned = CreateParameter("@RETURN_VALUE", SqlDbType.Int, DBNull.Value, ParameterDirection.ReturnValue); - try +END")) { - TryExecuteNonQueryCommand(drop); - ExecuteNonQueryCommand(create); - - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) using (SqlBatch batch = new SqlBatch(conn)) { - conn.Open(); batch.Commands.Add(new SqlBatchCommand("SELECT @@VERSION")); batch.Commands.Add( new SqlBatchCommand( - "TestInAndOutParams", + spTestInAndOutParams.Name, CommandType.StoredProcedure, new[] { input, inputOutput, output, returned } ) @@ -416,10 +409,6 @@ RETURN @Input batch.ExecuteNonQuery(); } } - finally - { - TryExecuteNonQueryCommand(drop); - } Assert.Equal(8, Convert.ToInt32(inputOutput.Value)); Assert.Equal(4, Convert.ToInt32(output.Value)); @@ -656,28 +645,5 @@ private static SqlParameter CreateParameter(string name, SqlDbType type, T va parameter.Value = value; return parameter; } - - private static void ExecuteNonQueryCommand(string command) - { - using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) - using (SqlCommand cmd = conn.CreateCommand()) - { - conn.Open(); - cmd.CommandText = command; - cmd.ExecuteNonQuery(); - } - } - private static bool TryExecuteNonQueryCommand(string command) - { - try - { - ExecuteNonQueryCommand(command); - return true; - } - catch - { - } - return false; - } } } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandCancelTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandCancelTest.cs index 552fd4cea5..f7f10c15e3 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandCancelTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandCancelTest.cs @@ -372,7 +372,9 @@ private static void ExecuteCommandCancelExpected(object state) string errorMessage = SystemDataResourceManager.Instance.SQL_OperationCancelled; string errorMessageSevereFailure = SystemDataResourceManager.Instance.SQL_SevereError; - DataTestUtility.ExpectFailure(() => + // This could fail with either a SqlException or an InvalidOperationException depending on timing, + // so we will accept either but require the message to match expected cancellation messages + DataTestUtility.ExpectFailure(() => { threadsReady.SignalAndWait(); using (SqlDataReader r = command.ExecuteReader()) @@ -384,7 +386,9 @@ private static void ExecuteCommandCancelExpected(object state) } } while (r.NextResult()); } - }, new string[] { errorMessage, errorMessageSevereFailure }); + }, + new string[] { errorMessage, errorMessageSevereFailure }, + customExceptionVerifier: (ex) => ex is SqlException or InvalidOperationException); } diff --git a/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/LocalAppContextSwitchesTest.cs b/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/LocalAppContextSwitchesTest.cs index a468d8fd37..a2fb1146b4 100644 --- a/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/LocalAppContextSwitchesTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft/Data/SqlClient/LocalAppContextSwitchesTest.cs @@ -1,8 +1,9 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // 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 Microsoft.Data.SqlClient.Tests.Common; using Xunit; namespace Microsoft.Data.SqlClient.UnitTests; @@ -18,26 +19,28 @@ public class LocalAppContextSwitchesTest [Fact] public void TestDefaultAppContextSwitchValues() { - Assert.False(LocalAppContextSwitches.LegacyRowVersionNullBehavior); - Assert.False(LocalAppContextSwitches.SuppressInsecureTlsWarning); - Assert.False(LocalAppContextSwitches.MakeReadAsyncBlocking); - Assert.True(LocalAppContextSwitches.UseMinimumLoginTimeout); - Assert.True(LocalAppContextSwitches.LegacyVarTimeZeroScaleBehaviour); - Assert.True(LocalAppContextSwitches.UseCompatibilityProcessSni); - Assert.True(LocalAppContextSwitches.UseCompatibilityAsyncBehaviour); - Assert.False(LocalAppContextSwitches.UseConnectionPoolV2); - Assert.False(LocalAppContextSwitches.TruncateScaledDecimal); - Assert.False(LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner); - Assert.False(LocalAppContextSwitches.UseLegacyFailoverAlternationOnLoginSqlErrors); - Assert.False(LocalAppContextSwitches.EnableMultiSubnetFailoverByDefault); + using LocalAppContextSwitchesHelper appContextSwitchesHelper = new(); + + Assert.False(appContextSwitchesHelper.LegacyRowVersionNullBehavior); + Assert.False(appContextSwitchesHelper.SuppressInsecureTlsWarning); + Assert.False(appContextSwitchesHelper.MakeReadAsyncBlocking); + Assert.True(appContextSwitchesHelper.UseMinimumLoginTimeout); + Assert.True(appContextSwitchesHelper.LegacyVarTimeZeroScaleBehaviour); + Assert.True(appContextSwitchesHelper.UseCompatibilityProcessSni); + Assert.True(appContextSwitchesHelper.UseCompatibilityAsyncBehaviour); + Assert.False(appContextSwitchesHelper.UseConnectionPoolV2); + Assert.False(appContextSwitchesHelper.TruncateScaledDecimal); + Assert.False(appContextSwitchesHelper.IgnoreServerProvidedFailoverPartner); + Assert.False(appContextSwitchesHelper.UseLegacyFailoverAlternationOnLoginSqlErrors); + Assert.False(appContextSwitchesHelper.EnableMultiSubnetFailoverByDefault); #if NET - Assert.False(LocalAppContextSwitches.GlobalizationInvariantMode); + Assert.False(appContextSwitchesHelper.GlobalizationInvariantMode); #endif #if NET && _WINDOWS - Assert.False(LocalAppContextSwitches.UseManagedNetworking); + Assert.False(appContextSwitchesHelper.UseManagedNetworking); #endif #if NETFRAMEWORK - Assert.False(LocalAppContextSwitches.DisableTnirByDefault); + Assert.False(appContextSwitchesHelper.DisableTnirByDefault); #endif } }