Imported Upstream version 5.4.0.167

Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-08-21 15:34:15 +00:00
parent e49d6f06c0
commit 536cd135cc
12856 changed files with 563812 additions and 223249 deletions

View File

@@ -2,9 +2,9 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\dir.props" />
<PropertyGroup>
<AssemblyVersion>4.2.0.0</AssemblyVersion>
<AssemblyVersion>4.2.1.0</AssemblyVersion>
<AssemblyKey>MSFT</AssemblyKey>
<IsNETCoreApp>true</IsNETCoreApp>
<IsDesktopFacade>true</IsDesktopFacade>
<IsUAP>true</IsUAP>
</PropertyGroup>
</Project>

View File

@@ -3,20 +3,30 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<ProjectReference Include="..\ref\System.ComponentModel.Annotations.csproj">
<SupportedFramework>net463;netcoreapp2.0;$(AllXamarinFrameworks)</SupportedFramework>
<SupportedFramework>net461;netcoreapp2.0;$(AllXamarinFrameworks)</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.ComponentModel.Annotations.csproj" />
<HarvestIncludePaths Include="ref/netcore50;lib/netcore50" />
<HarvestIncludePaths Include="ref/netstandard1.1" />
<HarvestIncludePaths Include="ref/netstandard1.3" />
<HarvestIncludePaths Include="ref/netstandard1.4;lib/netstandard1.4" />
<InboxOnTargetFramework Include="MonoAndroid10" />
<InboxOnTargetFramework Include="MonoTouch10" />
<InboxOnTargetFramework Include="net45">
<FrameworkReference>System.ComponentModel.DataAnnotations</FrameworkReference>
</InboxOnTargetFramework>
<InboxOnTargetFramework Include="netcoreapp2.0" />
<InboxOnTargetFramework Include="uap10.1" />
<InboxOnTargetFramework Include="win8" />
<InboxOnTargetFramework Include="portable-net45+win8" />
<InboxOnTargetFramework Include="xamarinios10" />
<InboxOnTargetFramework Include="xamarinmac20" />
<InboxOnTargetFramework Include="xamarintvos10" />
<InboxOnTargetFramework Include="xamarinwatchos10" />
<ValidatePackageSuppression Include="PermitMissingImplementation">
<!-- Supported inbox by all ns1.1-1.3 frameworks -->
<Value>.NETStandard,Version=v1.1;.NETStandard,Version=v1.2;.NETStandard,Version=v1.3</Value>
</ValidatePackageSuppression>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@@ -3,6 +3,7 @@
<PropertyGroup>
<BuildConfigurations>
netstandard;
netfx;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -122,6 +122,8 @@ namespace System.ComponentModel.DataAnnotations
public string DataFormatString { get { throw null; } set { } }
public bool HtmlEncode { get { throw null; } set { } }
public string NullDisplayText { get { throw null; } set { } }
public Type NullDisplayTextResourceType { get { throw null; } set { } }
public string GetNullDisplayText() { throw null; }
}
[System.AttributeUsageAttribute((System.AttributeTargets)(384), AllowMultiple = false, Inherited = true)]
public sealed partial class EditableAttribute : System.Attribute

View File

@@ -3,11 +3,18 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<ProjectGuid>{C4D6F1F4-DC7E-4756-9A88-171A8B1F1E26}</ProjectGuid>
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netfx'">true</IsPartialFacadeAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="System.ComponentModel.Annotations.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netfx'">
<Reference Include="mscorlib" />
<Reference Include="System.ComponentModel.DataAnnotations" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@@ -38,8 +38,6 @@ namespace System.ComponentModel.DataAnnotations
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
// TODO - check that GetRuntimeProperty() returns the same as old ObjectType.GetProperty()
// in all situations regardless of property modifiers
var otherPropertyInfo = validationContext.ObjectType.GetRuntimeProperty(OtherProperty);
if (otherPropertyInfo == null)
{
@@ -47,6 +45,11 @@ namespace System.ComponentModel.DataAnnotations
new ValidationResult(string.Format(CultureInfo.CurrentCulture,
SR.CompareAttribute_UnknownProperty, OtherProperty));
}
if (otherPropertyInfo.GetIndexParameters().Any())
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
SR.Common_PropertyNotFound, validationContext.ObjectType.FullName, OtherProperty));
}
object otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
if (!Equals(value, otherPropertyValue))
@@ -66,8 +69,7 @@ namespace System.ComponentModel.DataAnnotations
.SingleOrDefault(
prop =>
IsPublic(prop) &&
string.Equals(propertyName, prop.Name, StringComparison.OrdinalIgnoreCase) &&
!prop.GetIndexParameters().Any());
string.Equals(propertyName, prop.Name, StringComparison.OrdinalIgnoreCase));
if (property == null)
{

View File

@@ -11,6 +11,8 @@ namespace System.ComponentModel.DataAnnotations
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class DisplayFormatAttribute : Attribute
{
private readonly LocalizableString _nullDisplayText = new LocalizableString("NullDisplayText");
/// <summary>
/// Default constructor
/// </summary>
@@ -27,9 +29,29 @@ namespace System.ComponentModel.DataAnnotations
public string DataFormatString { get; set; }
/// <summary>
/// Gets or sets the string to display when the value is null
/// Gets or sets the string to display when the value is null, which may be a resource key string.
/// <para>
/// Consumers should use the <see cref="GetNullDisplayText" /> method to retrieve the UI display string.
/// </para>
/// </summary>
public string NullDisplayText { get; set; }
/// <remarks>
/// The property contains either the literal, non-localized string or the resource key
/// to be used in conjunction with <see cref="NullDisplayTextResourceType" /> to configure a localized
/// name for display.
/// <para>
/// The <see cref="GetNullDisplayText" /> method will return either the literal, non-localized
/// string or the localized string when <see cref="NullDisplayTextResourceType" /> has been specified.
/// </para>
/// </remarks>
/// <value>
/// The null dispay text is generally used as placeholder when the value is not specified.
/// A <c>null</c> or empty string is legal, and consumers must allow for that.
/// </value>
public string NullDisplayText
{
get { return _nullDisplayText.Value; }
set { _nullDisplayText.Value = value; }
}
/// <summary>
/// Gets or sets a value indicating whether empty strings should be set to null
@@ -45,5 +67,45 @@ namespace System.ComponentModel.DataAnnotations
/// Gets or sets a value indicating whether the field should be html encoded
/// </summary>
public bool HtmlEncode { get; set; }
/// <summary>
/// Gets or sets the <see cref="Type" /> that contains the resources for <see cref="NullDisplayText" />.
/// Using <see cref="NullDisplayTextResourceType" /> along with <see cref="NullDisplayText" />, allows the <see cref="GetNullDisplayText" />
/// method to return localized values.
/// </summary>
public Type NullDisplayTextResourceType
{
get { return _nullDisplayText.ResourceType; }
set { _nullDisplayText.ResourceType = value; }
}
/// <summary>
/// Gets the UI display string for NullDisplayText.
/// <para>
/// This can be either a literal, non-localized string provided to <see cref="NullDisplayText" /> or the
/// localized string found when <see cref="NullDisplayTextResourceType" /> has been specified and <see cref="NullDisplayText" />
/// represents a resource key within that resource type.
/// </para>
/// </summary>
/// <returns>
/// When <see cref="NullDisplayTextResourceType" /> has not been specified, the value of
/// <see cref="NullDisplayText" /> will be returned.
/// <para>
/// When <see cref="NullDisplayTextResourceType" /> has been specified and <see cref="NullDisplayText" />
/// represents a resource key within that resource type, then the localized value will be returned.
/// </para>
/// <para>
/// When <see cref="NullDisplayText" /> and <see cref="NullDisplayTextResourceType" /> have not been set, returns <c>null</c>.
/// </para>
/// </returns>
/// <exception cref="InvalidOperationException">
/// After setting both the <see cref="NullDisplayTextResourceType" /> property and the <see cref="NullDisplayText" /> property,
/// but a public static property with a name matching the <see cref="NullDisplayText" /> value couldn't be found
/// on the <see cref="NullDisplayTextResourceType" />.
/// </exception>
public string GetNullDisplayText()
{
return _nullDisplayText.GetLocalizableValue();
}
}
}

View File

@@ -122,8 +122,6 @@ namespace System.ComponentModel.DataAnnotations
else
{
// Get the property from the resource type for this resource key
// TODO - check that GetRuntimeProperty() returns the same as old GetProperty()
// in all situations regardless of property modifiers
var property = _resourceType.GetRuntimeProperty(_propertyValue);
// We need to detect bad configurations so that we can throw exceptions accordingly

View File

@@ -197,13 +197,11 @@ namespace System.ComponentModel.DataAnnotations
comparableType.FullName));
}
Func<object, object> conversion =
value =>
(value != null && value.GetType() == type)
? value
: Convert.ChangeType(value, type, CultureInfo.CurrentCulture);
var min = (IComparable)conversion(minimum);
var max = (IComparable)conversion(maximum);
TypeConverter converter = TypeDescriptor.GetConverter(type);
IComparable min = (IComparable)converter.ConvertFromString((string)minimum);
IComparable max = (IComparable)converter.ConvertFromString((string)maximum);
Func<object, object> conversion = value => (value != null && value.GetType() == type) ? value : converter.ConvertFrom(value);
Initialize(min, max, conversion);
}
}

View File

@@ -78,6 +78,7 @@ namespace System.ComponentModel.DataAnnotations
protected ValidationException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
throw new PlatformNotSupportedException();
}
/// <summary>

View File

@@ -462,9 +462,8 @@ nameof(value));
return errors;
}
// Step 3: Test for IValidatableObject implementation
var validatable = instance as IValidatableObject;
if (validatable != null)
// Step 3: Test for IValidatableObject implementation
if (instance is IValidatableObject validatable)
{
var results = validatable.Validate(validationContext);

View File

@@ -28,7 +28,7 @@ namespace System.ComponentModel.DataAnnotations.Tests
[Fact]
public static void Constructor_NullOtherProperty_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>("otherProperty", () => new CompareAttribute(null));
AssertExtensions.Throws<ArgumentNullException>("otherProperty", () => new CompareAttribute(null));
}
[Theory]
@@ -41,14 +41,23 @@ namespace System.ComponentModel.DataAnnotations.Tests
Assert.True(attribute.RequiresValidationContext);
}
[Fact]
public static void Validate_Indexer_ThrowsTargetParameterCountException()
[SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework)]
public static void Validate_Indexer_ThrowsTargetParameterCountException_Netfx()
{
CompareAttribute attribute = new CompareAttribute("Item");
Assert.Throws<TargetParameterCountException>(() => attribute.Validate("b", s_context));
}
[Fact]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)]
public static void Validate_Indexer_ThrowsArgumentException_Netcoreapp()
{
CompareAttribute attribute = new CompareAttribute("Item");
Assert.Throws<ArgumentException>(null, () => attribute.Validate("b", s_context));
}
[Fact]
public static void Validate_SetOnlyProperty_ThrowsArgumentException()
{

View File

@@ -77,7 +77,17 @@ namespace System.ComponentModel.DataAnnotations.Tests
public static void RequiresValidationContext_Get_ReturnsExpected(string method, bool expected)
{
CustomValidationAttribute attribute = GetAttribute(method);
Assert.Equal(expected, attribute.RequiresValidationContext);
// The full .NET Framework has a bug where CustomValidationAttribute doesn't
// validate the context. See https://github.com/dotnet/corefx/issues/18360.
if (PlatformDetection.IsFullFramework)
{
Assert.False(attribute.RequiresValidationContext);
}
else
{
Assert.Equal(expected, attribute.RequiresValidationContext);
}
}
public static IEnumerable<object[]> BadlyFormed_TestData()
@@ -96,13 +106,23 @@ namespace System.ComponentModel.DataAnnotations.Tests
}
[Theory]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, ".NET Core fixes a bug where CustomValidationAttribute doesn't validate the context. See https://github.com/dotnet/corefx/issues/18360")]
[MemberData(nameof(BadlyFormed_TestData))]
public static void RequiresValidationContext_BadlyFormed_ThrowsInvalidOperationException(Type validatorType, string method)
public static void RequiresValidationContext_BadlyFormed_NetCore_ThrowsInvalidOperationException(Type validatorType, string method)
{
CustomValidationAttribute attribute = new CustomValidationAttribute(validatorType, method);
Assert.Throws<InvalidOperationException>(() => attribute.RequiresValidationContext);
}
[Theory]
[SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework, "The full .NET Framework has a bug where CustomValidationAttribute doesn't validate the context. See https://github.com/dotnet/corefx/issues/18360")]
[MemberData(nameof(BadlyFormed_TestData))]
public static void RequiresValidationContext_BadlyFormed_NetFx_DoesNotThrow(Type validatorType, string method)
{
CustomValidationAttribute attribute = new CustomValidationAttribute(validatorType, method);
Assert.False(attribute.RequiresValidationContext);
}
[Theory]
[MemberData(nameof(BadlyFormed_TestData))]
public static void Validate_BadlyFormed_ThrowsInvalidOperationException(Type validatorType, string method)

View File

@@ -65,25 +65,33 @@ namespace System.ComponentModel.DataAnnotations.Tests
Assert.Throws<IndexOutOfRangeException>(() => attribute.GetDataTypeName());
}
public static IEnumerable<object[]> Ctor_String_TestData()
{
yield return new object[] { "CustomValue", true };
yield return new object[] { "", false };
yield return new object[] { null, false };
// .NET Core fixed a bug where whitespace strings were allowed as CustomDataType.
// See https://github.com/dotnet/corefx/issues/4465.
yield return new object[] { " ", PlatformDetection.IsFullFramework };
}
[Theory]
[InlineData("CustomValue")]
[InlineData("")]
[InlineData(" ")]
[InlineData(null)]
public static void Ctor_String(string customDataType)
[MemberData(nameof(Ctor_String_TestData))]
public static void Ctor_String(string customDataType, bool valid)
{
DataTypeAttribute attribute = new DataTypeAttribute(customDataType);
Assert.Equal(DataType.Custom, attribute.DataType);
Assert.Equal(customDataType, attribute.CustomDataType);
if (string.IsNullOrWhiteSpace(customDataType))
if (valid)
{
Assert.Throws<InvalidOperationException>(() => attribute.GetDataTypeName());
Assert.Throws<InvalidOperationException>(() => attribute.Validate(new object(), s_testValidationContext));
Assert.Equal(customDataType, attribute.GetDataTypeName());
}
else
{
Assert.Equal(customDataType, attribute.GetDataTypeName());
Assert.Throws<InvalidOperationException>(() => attribute.GetDataTypeName());
Assert.Throws<InvalidOperationException>(() => attribute.Validate(new object(), s_testValidationContext));
}
}

View File

@@ -0,0 +1,154 @@
// 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.Collections.Generic;
using Xunit;
namespace System.ComponentModel.DataAnnotations.Tests
{
public class DisplayFormatAttributeTest
{
[Fact]
public void Ctor()
{
DisplayFormatAttribute attribute = new DisplayFormatAttribute();
Assert.True(attribute.ConvertEmptyStringToNull);
Assert.True(attribute.HtmlEncode);
Assert.False(attribute.ApplyFormatInEditMode);
Assert.Null(attribute.DataFormatString);
Assert.Null(attribute.NullDisplayText);
#if netcoreapp
Assert.Null(attribute.NullDisplayTextResourceType);
#endif
}
[Theory]
[InlineData("{0:C}")]
[InlineData("{0:d}")]
public void DataFormatString_Get_Set(string input)
{
DisplayFormatAttribute attribute = new DisplayFormatAttribute();
attribute.DataFormatString = input;
Assert.Equal(input, attribute.DataFormatString);
}
[Fact]
public void ConvertEmptyStringToNull_Get_Set()
{
DisplayFormatAttribute attribute = new DisplayFormatAttribute();
attribute.ConvertEmptyStringToNull = false;
Assert.False(attribute.ConvertEmptyStringToNull);
}
[Fact]
public void ApplyFormatInEditMode_Get_Set()
{
DisplayFormatAttribute attribute = new DisplayFormatAttribute();
attribute.ApplyFormatInEditMode = true;
Assert.True(attribute.ApplyFormatInEditMode);
}
[Fact]
public void HtmlEncode_Get_Set()
{
DisplayFormatAttribute attribute = new DisplayFormatAttribute();
attribute.HtmlEncode = false;
Assert.False(attribute.HtmlEncode);
}
public static IEnumerable<object[]> Strings_TestData()
{
yield return new object[] { "" };
yield return new object[] { " \r \t \n " };
yield return new object[] { "abc" };
yield return new object[] { "NullDisplayText" };
}
[Theory]
[MemberData(nameof(Strings_TestData))]
public void NullDisplayText_Get_Set(string input)
{
DisplayFormatAttribute attribute = new DisplayFormatAttribute();
attribute.NullDisplayText = input;
Assert.Equal(input, attribute.NullDisplayText);
#if netcoreapp
Assert.NotNull(attribute.GetNullDisplayText());
#endif
// Set again, to cover the setter avoiding operations if the value is the same
attribute.NullDisplayText = input;
Assert.Equal(input, attribute.NullDisplayText);
}
#if netcoreapp
public class FakeResourceType
{
public static string Resource1
{
get { return "Resource1Text"; }
}
public static string Resource2
{
get { return "Resource2Text"; }
}
}
[Fact]
public void NullDisplayTextResourceType_Get_Set()
{
DisplayFormatAttribute attribute = new DisplayFormatAttribute();
attribute.NullDisplayTextResourceType = typeof(FakeResourceType);
Assert.Equal(typeof(FakeResourceType), attribute.NullDisplayTextResourceType);
}
[Fact]
public void NullDisplayText_WithResource()
{
DisplayFormatAttribute attribute = new DisplayFormatAttribute();
attribute.NullDisplayTextResourceType = typeof(FakeResourceType);
attribute.NullDisplayText = "Resource1";
Assert.Equal(FakeResourceType.Resource1, attribute.GetNullDisplayText());
// Changing target resource
attribute.NullDisplayText = "Resource2";
Assert.Equal(FakeResourceType.Resource2, attribute.GetNullDisplayText());
// Not existing resource in the resource type
attribute.NullDisplayText = "Resource3";
Assert.Throws<InvalidOperationException>(() => attribute.GetNullDisplayText());
}
[Fact]
public void NullDisplayText_NotAResourceType()
{
DisplayFormatAttribute attribute = new DisplayFormatAttribute();
// Setting a type that is not a resource type
attribute.NullDisplayTextResourceType = typeof(string);
attribute.NullDisplayText = "foo";
Assert.Throws<InvalidOperationException>(() => attribute.GetNullDisplayText());
}
[Theory]
[InlineData(null)]
[InlineData(typeof(FakeResourceType))]
public void GetNullDisplayText_WhenNullDisplayTextNotSet(Type input)
{
DisplayFormatAttribute attribute = new DisplayFormatAttribute();
attribute.NullDisplayTextResourceType = input;
Assert.Null(attribute.GetNullDisplayText());
}
#endif
}
}

View File

@@ -20,27 +20,35 @@ namespace System.ComponentModel.DataAnnotations.Tests
yield return new TestCase(new MaxLengthAttribute(-1), new int[20]);
yield return new TestCase(new MaxLengthAttribute(15), new string[14]);
yield return new TestCase(new MaxLengthAttribute(16), new string[16]);
yield return new TestCase(new MaxLengthAttribute(-1), new Collection<int>(new int[20]));
yield return new TestCase(new MaxLengthAttribute(15), new Collection<string>(new string[14]));
yield return new TestCase(new MaxLengthAttribute(16), new Collection<string>(new string[16]));
yield return new TestCase(new MaxLengthAttribute(-1), new List<int>(new int[20]));
yield return new TestCase(new MaxLengthAttribute(15), new List<string>(new string[14]));
yield return new TestCase(new MaxLengthAttribute(16), new List<string>(new string[16]));
yield return new TestCase(new MaxLengthAttribute(16), new int[4, 4]);
yield return new TestCase(new MaxLengthAttribute(16), new string[3, 4]);
}
protected static IEnumerable<object[]> ValidValues_ICollection()
{
yield return new object[] { new MaxLengthAttribute(-1), new Collection<int>(new int[20]) };
yield return new object[] { new MaxLengthAttribute(15), new Collection<string>(new string[14]) };
yield return new object[] { new MaxLengthAttribute(16), new Collection<string>(new string[16]) };
yield return new object[] { new MaxLengthAttribute(-1), new List<int>(new int[20]) };
yield return new object[] { new MaxLengthAttribute(15), new List<string>(new string[14]) };
yield return new object[] { new MaxLengthAttribute(16), new List<string>(new string[16]) };
}
protected override IEnumerable<TestCase> InvalidValues()
{
yield return new TestCase(new MaxLengthAttribute(12), "OverMaxLength");
yield return new TestCase(new MaxLengthAttribute(12), new byte[13]);
yield return new TestCase(new MaxLengthAttribute(12), new Collection<byte>(new byte[13]));
yield return new TestCase(new MaxLengthAttribute(12), new List<byte>(new byte[13]));
yield return new TestCase(new MaxLengthAttribute(12), new int[4, 4]);
}
protected static IEnumerable<object> InvalidValues_ICollection()
{
yield return new object[] { new MaxLengthAttribute(12), new Collection<byte>(new byte[13]) };
yield return new object[] { new MaxLengthAttribute(12), new List<byte>(new byte[13]) };
}
[Fact]
public static void Ctor()
{
@@ -57,6 +65,34 @@ namespace System.ComponentModel.DataAnnotations.Tests
Assert.Equal(length, new MaxLengthAttribute(length).Length);
}
[Theory]
[MemberData(nameof(ValidValues_ICollection))]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "MaxLengthAttribute in the .NET Framework doesn't support ICollection.Count. See https://github.com/dotnet/corefx/issues/18361")]
public void Validate_ICollection_NetCore_Valid(MaxLengthAttribute attribute, object value)
{
attribute.Validate(value, new ValidationContext(new object()));
Assert.True(attribute.IsValid(value));
}
[Theory]
[MemberData(nameof(InvalidValues_ICollection))]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "MaxLengthAttribute in the .NET Framework doesn't support ICollection.Count. See https://github.com/dotnet/corefx/issues/18361")]
public void Validate_ICollection_NetCore_Invalid(MaxLengthAttribute attribute, object value)
{
Assert.Throws<ValidationException>(() => attribute.Validate(value, new ValidationContext(new object())));
Assert.False(attribute.IsValid(value));
}
[Theory]
[MemberData(nameof(ValidValues_ICollection))]
[MemberData(nameof(InvalidValues_ICollection))]
[SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework, "MaxLengthAttribute in the .NET Core supports ICollection.Count. See https://github.com/dotnet/corefx/issues/18361")]
public void Validate_ICollection_NetFx_ThrowsInvalidCastException(MaxLengthAttribute attribute, object value)
{
Assert.Throws<InvalidCastException>(() => attribute.Validate(value, new ValidationContext(new object())));
Assert.Throws<InvalidCastException>(() => attribute.IsValid(value));
}
[Theory]
[InlineData(0)]
[InlineData(-10)]

View File

@@ -20,26 +20,33 @@ namespace System.ComponentModel.DataAnnotations.Tests
yield return new TestCase(new MinLengthAttribute(0), new int[0]);
yield return new TestCase(new MinLengthAttribute(12), new int[14]);
yield return new TestCase(new MinLengthAttribute(16), new string[16]);
}
yield return new TestCase(new MinLengthAttribute(0), new Collection<int>(new int[0]));
yield return new TestCase(new MinLengthAttribute(12), new Collection<int>(new int[14]));
yield return new TestCase(new MinLengthAttribute(16), new Collection<string>(new string[16]));
protected static IEnumerable<object[]> ValidValues_ICollection()
{
yield return new object[] { new MinLengthAttribute(0), new Collection<int>(new int[0]) };
yield return new object[] { new MinLengthAttribute(12), new Collection<int>(new int[14]) };
yield return new object[] { new MinLengthAttribute(16), new Collection<string>(new string[16]) };
yield return new TestCase(new MinLengthAttribute(0), new List<int>(new int[0]));
yield return new TestCase(new MinLengthAttribute(12), new List<int>(new int[14]));
yield return new TestCase(new MinLengthAttribute(16), new List<string>(new string[16]));
yield return new object[] { new MinLengthAttribute(0), new List<int>(new int[0]) };
yield return new object[] { new MinLengthAttribute(12), new List<int>(new int[14]) };
yield return new object[] { new MinLengthAttribute(16), new List<string>(new string[16]) };
}
protected override IEnumerable<TestCase> InvalidValues()
{
yield return new TestCase(new MinLengthAttribute(15), "UnderMinLength");
yield return new TestCase(new MinLengthAttribute(15), new byte[14]);
yield return new TestCase(new MinLengthAttribute(15), new Collection<byte>(new byte[14]));
yield return new TestCase(new MinLengthAttribute(15), new List<byte>(new byte[14]));
yield return new TestCase(new MinLengthAttribute(12), new int[3, 3]);
}
protected static IEnumerable<object[]> InvalidValues_ICollection()
{
yield return new object[] { new MinLengthAttribute(15), new Collection<byte>(new byte[14]) };
yield return new object[] { new MinLengthAttribute(15), new List<byte>(new byte[14]) };
}
[Theory]
[InlineData(10)]
[InlineData(0)]
@@ -49,6 +56,34 @@ namespace System.ComponentModel.DataAnnotations.Tests
Assert.Equal(length, new MinLengthAttribute(length).Length);
}
[Theory]
[MemberData(nameof(ValidValues_ICollection))]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "MinLengthAttribute in the .NET Framework doesn't support ICollection.Count. See https://github.com/dotnet/corefx/issues/18361")]
public void Validate_ICollection_NetCore_Valid(MinLengthAttribute attribute, object value)
{
attribute.Validate(value, new ValidationContext(new object()));
Assert.True(attribute.IsValid(value));
}
[Theory]
[MemberData(nameof(InvalidValues_ICollection))]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "MinLengthAttribute in the .NET Framework doesn't support ICollection.Count. See https://github.com/dotnet/corefx/issues/18361")]
public void Validate_ICollection_NetCore_Invalid(MinLengthAttribute attribute, object value)
{
Assert.Throws<ValidationException>(() => attribute.Validate(value, new ValidationContext(new object())));
Assert.False(attribute.IsValid(value));
}
[Theory]
[MemberData(nameof(ValidValues_ICollection))]
[MemberData(nameof(InvalidValues_ICollection))]
[SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework, "MinLengthAttribute in .NET Core supports ICollection.Count. See https://github.com/dotnet/corefx/issues/18361")]
public void Validate_ICollection_NetFx_ThrowsInvalidCastException(MinLengthAttribute attribute, object value)
{
Assert.Throws<InvalidCastException>(() => attribute.Validate(value, new ValidationContext(new object())));
Assert.Throws<InvalidCastException>(() => attribute.IsValid(value));
}
[Fact]
public static void GetValidationResult_InvalidLength_ThrowsInvalidOperationException()
{

View File

@@ -24,12 +24,6 @@ namespace System.ComponentModel.DataAnnotations.Tests
yield return new TestCase(new PhoneAttribute(), "425-555-1212 ext.123");
yield return new TestCase(new PhoneAttribute(), "425-555-1212 ext. 123");
yield return new TestCase(new PhoneAttribute(), "1");
yield return new TestCase(new PhoneAttribute(), "+4+2+5+-+5+5+5+-+1+2++1+2++");
yield return new TestCase(new PhoneAttribute(), "425-555-1212 ");
yield return new TestCase(new PhoneAttribute(), " \r \n 1 \t ");
yield return new TestCase(new PhoneAttribute(), "1-.()");
yield return new TestCase(new PhoneAttribute(), "(425555-1212");
yield return new TestCase(new PhoneAttribute(), ")425555-1212");
}
protected override IEnumerable<TestCase> InvalidValues()
@@ -46,6 +40,20 @@ namespace System.ComponentModel.DataAnnotations.Tests
yield return new TestCase(new PhoneAttribute(), "425-555-1212 ext. xyz");
yield return new TestCase(new PhoneAttribute(), "-.()");
yield return new TestCase(new PhoneAttribute(), "ext.123 1");
// Certain invalid phone numbers are reported as valid with .NET core.
// The full .NET framework considers them invalid. This is likely a bug
// in .NET core. Seee https://github.com/dotnet/corefx/issues/17873.
// [ActiveIssue(17873)]
if (PlatformDetection.IsFullFramework)
{
yield return new TestCase(new PhoneAttribute(), "+4+2+5+-+5+5+5+-+1+2++1+2++");
yield return new TestCase(new PhoneAttribute(), "425-555-1212 ");
yield return new TestCase(new PhoneAttribute(), " \r \n 1 \t ");
yield return new TestCase(new PhoneAttribute(), "1-.()");
yield return new TestCase(new PhoneAttribute(), "(425555-1212");
yield return new TestCase(new PhoneAttribute(), ")425555-1212");
}
}
[Fact]

View File

@@ -71,7 +71,6 @@ namespace System.ComponentModel.DataAnnotations.Tests
yield return new TestCase(stringIntRange, "0");
yield return new TestCase(stringIntRange, 4);
yield return new TestCase(stringIntRange, "4");
yield return new TestCase(stringIntRange, "abc");
yield return new TestCase(stringIntRange, new object());
// Implements IConvertible (throws NotSupportedException - is caught)
yield return new TestCase(stringIntRange, new IConvertibleImplementor() { IntThrow = new NotSupportedException() });
@@ -81,12 +80,21 @@ namespace System.ComponentModel.DataAnnotations.Tests
yield return new TestCase(stringDoubleRange, (0.9999999).ToString());
yield return new TestCase(stringDoubleRange, 3.0000001);
yield return new TestCase(stringDoubleRange, (3.0000001).ToString());
yield return new TestCase(stringDoubleRange, "abc");
yield return new TestCase(stringDoubleRange, new object());
// Implements IConvertible (throws NotSupportedException - is caught)
yield return new TestCase(stringDoubleRange, new IConvertibleImplementor() { DoubleThrow = new NotSupportedException() });
}
[Theory]
[InlineData(typeof(int), "1", "3")]
[InlineData(typeof(double), "1", "3")]
public static void Validate_CantConvertValueToTargetType_ThrowsException(Type type, string minimum, string maximum)
{
var attribute = new RangeAttribute(type, minimum, maximum);
Assert.Throws<Exception>(() => attribute.Validate("abc", new ValidationContext(new object())));
Assert.Throws<Exception>(() => attribute.IsValid("abc"));
}
[Fact]
public static void Ctor_Int_Int()
{
@@ -152,15 +160,21 @@ namespace System.ComponentModel.DataAnnotations.Tests
RangeAttribute attribute = new RangeAttribute(typeof(int), minimum, maximum);
Assert.Throws<InvalidOperationException>(() => attribute.Validate("Any", new ValidationContext(new object())));
}
[Theory]
[InlineData(typeof(DateTime), "Cannot Convert", "2014-03-19")]
[InlineData(typeof(DateTime), "2014-03-19", "Cannot Convert")]
[InlineData(typeof(int), "Cannot Convert", "3")]
[InlineData(typeof(int), "1", "Cannot Convert")]
[InlineData(typeof(double), "Cannot Convert", "3")]
[InlineData(typeof(double), "1", "Cannot Convert")]
public static void Validate_MinimumOrMaximumCantBeConvertedToType_ThrowsFormatException(Type type, string minimum, string maximum)
public static void Validate_MinimumOrMaximumCantBeConvertedToIntegralType_ThrowsException(Type type, string minimum, string maximum)
{
RangeAttribute attribute = new RangeAttribute(type, minimum, maximum);
Assert.Throws<Exception>(() => attribute.Validate("Any", new ValidationContext(new object())));
}
[Theory]
[InlineData(typeof(DateTime), "Cannot Convert", "2014-03-19")]
[InlineData(typeof(DateTime), "2014-03-19", "Cannot Convert")]
public static void Validate_MinimumOrMaximumCantBeConvertedToDateTime_ThrowsFormatException(Type type, string minimum, string maximum)
{
RangeAttribute attribute = new RangeAttribute(type, minimum, maximum);
Assert.Throws<FormatException>(() => attribute.Validate("Any", new ValidationContext(new object())));
@@ -188,7 +202,7 @@ namespace System.ComponentModel.DataAnnotations.Tests
public static void Validate_IConvertibleThrowsCustomException_IsNotCaught()
{
RangeAttribute attribute = new RangeAttribute(typeof(int), "1", "1");
Assert.Throws<ArithmeticException>(() => attribute.Validate(new IConvertibleImplementor() { IntThrow = new ArithmeticException() }, new ValidationContext(new object())));
Assert.Throws<ValidationException>(() => attribute.Validate(new IConvertibleImplementor() { IntThrow = new ArithmeticException() }, new ValidationContext(new object())));
}
}
}

View File

@@ -72,7 +72,7 @@ namespace System.ComponentModel.DataAnnotations.Tests
public static void Validate_InvalidMatchTimeoutInMilliseconds_ThrowsArgumentOutOfRangeException(int timeout)
{
RegularExpressionAttribute attribute = new RegularExpressionAttribute("[^a]+\\.[^z]+") { MatchTimeoutInMilliseconds = 0 };
Assert.Throws<ArgumentOutOfRangeException>("matchTimeout", () => attribute.Validate("a", new ValidationContext(new object())));
AssertExtensions.Throws<ArgumentOutOfRangeException>("matchTimeout", () => attribute.Validate("a", new ValidationContext(new object())));
}
[Fact]

Some files were not shown because too many files have changed in this diff Show More