
committed by
GitHub

No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 258 additions and 1 deletions
-
3.gitignore
-
2src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBuffer.cs
-
1src/Microsoft.Data.SqlClient/tests/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj
-
253src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlBufferTests.cs
@ -0,0 +1,253 @@ |
|||||
|
// 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 System.Collections.Generic; |
||||
|
using System.Data.SqlTypes; |
||||
|
using System.Linq; |
||||
|
using System.Reflection; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Microsoft.Data.SqlClient.Tests |
||||
|
{ |
||||
|
public sealed class SqlBufferTests |
||||
|
{ |
||||
|
static SqlBufferTests() |
||||
|
{ |
||||
|
const string sqlBufferTypeFullName = "Microsoft.Data.SqlClient.SqlBuffer"; |
||||
|
const string storageTypeName = nameof(SqlBufferProxy.StorageType); |
||||
|
|
||||
|
var assembly = typeof(SqlClientFactory).Assembly; |
||||
|
_sqlBufferType = assembly.GetType(sqlBufferTypeFullName) |
||||
|
?? throw new Exception($"Type not found [{sqlBufferTypeFullName}]"); |
||||
|
_storageTypeType = _sqlBufferType.GetNestedTypes(BindingFlags.NonPublic) |
||||
|
.FirstOrDefault(x => x.Name == storageTypeName) |
||||
|
?? throw new Exception($"Type not found [{sqlBufferTypeFullName}+{storageTypeName}]"); |
||||
|
} |
||||
|
|
||||
|
private static readonly Type _sqlBufferType; |
||||
|
private static readonly Type _storageTypeType; |
||||
|
private readonly SqlBufferProxy _target = new(); |
||||
|
|
||||
|
public static IEnumerable<object[]> GetStorageTypeValues() |
||||
|
{ |
||||
|
#if NET6_0_OR_GREATER
|
||||
|
return Enum.GetValues<SqlBufferProxy.StorageType>() |
||||
|
.Select(x => new object[] { x }); |
||||
|
#else
|
||||
|
return Enum.GetValues(typeof(SqlBufferProxy.StorageType)) |
||||
|
.OfType<SqlBufferProxy.StorageType>() |
||||
|
.Select(x => new object[] { x }); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[MemberData(nameof(GetStorageTypeValues))] |
||||
|
public void StorageTypeInProxyShouldHaveTheSameValueAsOriginal(SqlBufferProxy.StorageType expected) |
||||
|
{ |
||||
|
var originalEnumName = Enum.GetName(_storageTypeType, (int)expected); |
||||
|
|
||||
|
Assert.Equal(expected.ToString(), originalEnumName); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void GuidShouldThrowWhenSqlGuidNullIsSet() |
||||
|
{ |
||||
|
_target.SqlGuid = SqlGuid.Null; |
||||
|
|
||||
|
Assert.Throws<SqlNullValueException>(() => _target.Guid); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(SqlBufferProxy.StorageType.Guid)] |
||||
|
[InlineData(SqlBufferProxy.StorageType.SqlGuid)] |
||||
|
public void GuidShouldThrowWhenSetToNullOfTypeIsCalled(SqlBufferProxy.StorageType storageType) |
||||
|
{ |
||||
|
_target.SetToNullOfType(storageType); |
||||
|
|
||||
|
Assert.Throws<SqlNullValueException>(() => _target.Guid); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void GuidShouldReturnWhenGuidIsSet() |
||||
|
{ |
||||
|
var expected = Guid.NewGuid(); |
||||
|
_target.Guid = expected; |
||||
|
|
||||
|
Assert.Equal(expected, _target.Guid); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void GuidShouldReturnExpectedWhenSqlGuidIsSet() |
||||
|
{ |
||||
|
var expected = Guid.NewGuid(); |
||||
|
_target.SqlGuid = expected; |
||||
|
|
||||
|
Assert.Equal(expected, _target.Guid); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[InlineData(SqlBufferProxy.StorageType.Guid)] |
||||
|
[InlineData(SqlBufferProxy.StorageType.SqlGuid)] |
||||
|
public void SqlGuidShouldReturnSqlNullWhenSetToNullOfTypeIsCalled(SqlBufferProxy.StorageType storageType) |
||||
|
{ |
||||
|
_target.SetToNullOfType(storageType); |
||||
|
|
||||
|
Assert.Equal(SqlGuid.Null, _target.SqlGuid); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SqlGuidShouldReturnSqlGuidNullWhenSqlGuidNullIsSet() |
||||
|
{ |
||||
|
_target.SqlGuid = SqlGuid.Null; |
||||
|
|
||||
|
Assert.Equal(SqlGuid.Null, _target.SqlGuid); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SqlGuidShouldReturnExpectedWhenGuidIsSet() |
||||
|
{ |
||||
|
var guid = Guid.NewGuid(); |
||||
|
SqlGuid expected = guid; |
||||
|
_target.Guid = guid; |
||||
|
|
||||
|
Assert.Equal(expected, _target.SqlGuid); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SqlGuidShouldReturnExpectedWhenSqlGuidIsSet() |
||||
|
{ |
||||
|
SqlGuid expected = Guid.NewGuid(); |
||||
|
_target.SqlGuid = expected; |
||||
|
|
||||
|
Assert.Equal(expected, _target.SqlGuid); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SqlValueShouldReturnExpectedWhenGuidIsSet() |
||||
|
{ |
||||
|
var guid = Guid.NewGuid(); |
||||
|
SqlGuid expected = guid; |
||||
|
_target.Guid = guid; |
||||
|
|
||||
|
Assert.Equal(expected, _target.SqlValue); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void SqlValueShouldReturnExpectedWhenSqlGuidIsSet() |
||||
|
{ |
||||
|
SqlGuid expected = Guid.NewGuid(); |
||||
|
_target.SqlGuid = expected; |
||||
|
|
||||
|
Assert.Equal(expected, _target.SqlValue); |
||||
|
} |
||||
|
|
||||
|
public sealed class SqlBufferProxy |
||||
|
{ |
||||
|
public enum StorageType |
||||
|
{ |
||||
|
Empty = 0, |
||||
|
Boolean, |
||||
|
Byte, |
||||
|
DateTime, |
||||
|
Decimal, |
||||
|
Double, |
||||
|
Int16, |
||||
|
Int32, |
||||
|
Int64, |
||||
|
Guid, |
||||
|
Money, |
||||
|
Single, |
||||
|
String, |
||||
|
SqlBinary, |
||||
|
SqlCachedBuffer, |
||||
|
SqlGuid, |
||||
|
SqlXml, |
||||
|
Date, |
||||
|
DateTime2, |
||||
|
DateTimeOffset, |
||||
|
Time, |
||||
|
} |
||||
|
|
||||
|
private static readonly PropertyInfo _guidProperty; |
||||
|
private static readonly PropertyInfo _sqlGuidProperty; |
||||
|
private static readonly PropertyInfo _sqlValueProperty; |
||||
|
private static readonly MethodInfo _setToNullOfTypeMethod; |
||||
|
private readonly object _instance; |
||||
|
|
||||
|
static SqlBufferProxy() |
||||
|
{ |
||||
|
var flags = BindingFlags.NonPublic | BindingFlags.Instance; |
||||
|
_guidProperty = _sqlBufferType.GetProperty(nameof(Guid), flags); |
||||
|
_sqlGuidProperty = _sqlBufferType.GetProperty(nameof(SqlGuid), flags); |
||||
|
_sqlValueProperty = _sqlBufferType.GetProperty(nameof(SqlValue), flags); |
||||
|
_setToNullOfTypeMethod = _sqlBufferType.GetMethod(nameof(SetToNullOfType), flags); |
||||
|
} |
||||
|
|
||||
|
public SqlBufferProxy() |
||||
|
{ |
||||
|
_instance = Activator.CreateInstance(_sqlBufferType, true); |
||||
|
} |
||||
|
|
||||
|
public Guid Guid |
||||
|
{ |
||||
|
get => GetPropertyValue<Guid>(_guidProperty); |
||||
|
set => SetPropertyValue(_guidProperty, value); |
||||
|
} |
||||
|
|
||||
|
public SqlGuid SqlGuid |
||||
|
{ |
||||
|
get => GetPropertyValue<SqlGuid>(_sqlGuidProperty); |
||||
|
set => SetPropertyValue(_sqlGuidProperty, value); |
||||
|
} |
||||
|
|
||||
|
public object SqlValue |
||||
|
{ |
||||
|
get => GetPropertyValue<object>(_sqlValueProperty); |
||||
|
} |
||||
|
|
||||
|
public void SetToNullOfType(StorageType storageType) |
||||
|
{ |
||||
|
#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
|
||||
|
_setToNullOfTypeMethod |
||||
|
.Invoke(_instance, BindingFlags.DoNotWrapExceptions, null, new object[] { (int)storageType }, null); |
||||
|
#else
|
||||
|
_setToNullOfTypeMethod.Invoke(_instance, new object[] { (int)storageType }); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
private T GetPropertyValue<T>(PropertyInfo property) |
||||
|
{ |
||||
|
#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
|
||||
|
return (T)property.GetValue(_instance, BindingFlags.DoNotWrapExceptions, null, null, null); |
||||
|
#else
|
||||
|
try |
||||
|
{ |
||||
|
return (T)property.GetValue(_instance); |
||||
|
} |
||||
|
catch (TargetInvocationException e) |
||||
|
{ |
||||
|
throw e.InnerException!; |
||||
|
} |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
private void SetPropertyValue(PropertyInfo property, object value) |
||||
|
{ |
||||
|
#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
|
||||
|
property.SetValue(_instance, value, BindingFlags.DoNotWrapExceptions, null, null, null); |
||||
|
#else
|
||||
|
try |
||||
|
{ |
||||
|
property.SetValue(_instance, value); |
||||
|
} |
||||
|
catch (TargetInvocationException e) |
||||
|
{ |
||||
|
throw e.InnerException!; |
||||
|
} |
||||
|
#endif
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue